python实现树结构
简述:
研究  MCTS 过程中,需要⽤到树结构。  baidu  google 了⼀番,不到⾃⼰能满⾜⾃⼰的库或代码参考,只好再造个轮⼦出来
我造的树⽤来下五⼦棋和围棋⽤的,有其它不同的应⽤场合,那就需要在此基础上改造了。
本树的特点:
1. ⽀持多⼦节点(⽹络上很多代码都是⼆叉树,不符合我的需求)
2. ⽀持树的存储和读取,⽹上很少看到。
正⽂:
下⾯按照应⽤场景,数据结构和接⼝,代码,三个部分⾃上向下说明。
应⽤场景:
二叉树的遍历python⼀:画⼀个根节点,再加三个叶⼦的树(参考 Tree.demo1())
data = ['{}'.format(  random.random() * 10000 )]
self.addSubNodeToCur_Data( data )
data = ['{}'.format(  random.random() * 10000 )]
self.addSubNodeToCur_Data( data )
data = ['{}'.format(  random.random() * 10000 )]
self.addSubNodeToCur_Data( data )
self.save()
初始化出来的树,只有⼀个根节点  tree = Tree()
然后在根下⾯,加⼀个节点,内容是 data ,必须是 list 结构,list ⾥的元素只能是 字符,数字, Tru
e/False , 不允许 object , list  , () moveUp 是当前节点往上移动⼀层,  如果已经是根节点了,会返回False
addSubNodeToCur_Data(self,  data, NodeId = 0, isMoveToSub = True )  在当前节点下,增加⼀个节点,节点内容是 Data
; isMoveToSub  当前节点移到新增节点
NodeId ⼀般不需要设置, 如果你的树结构是清楚的时候, 知道NodeId 的情况下设置。
⼆: 保存树,读取树
self.load(self, filename = None)    , load 之后,⽣成树
self.save(self, filename = None)
默认⽂件名 ./data.npy  可指定⽂件名,  .npy 结尾
三:⽣成棋谱树
该棋局,只有 4个落⼦点, [(0, 0), (0, 1), (1, 0), (1, 1)] ,⼀个⼈下
根据数理分析,会形成这样⼀棵树:
0                        root_node  根节点
1                  4 × node          第⼀步节点数
2                3  x  4  x node  第⼆步节点数
3              2x  3x4xnode      第三步节点数
4              1x  2x3x4xnode  第四步节点数
下⼀局,形成的⼀个棋谱
#  下⼀局,随机选⼀个点,下满棋盘
def WzOne( tree ):
action = random.choice(avilAction)  #随机⼀个落⼦点
data = list( action )
# 遍历当前前节点的⼦节点,如果已经存在该落⼦点,则跳到⼦节点
# 如果当前节点的⼦节点,⽆该落⼦点,则增加⼀个⼦节点
isExist = False
for node in tree.cur_Node.children :
if( Data() == data ):
isExist = True
break
if( isExist == False ):
tree.addSubNodeToCur_Data(data)
pass
下100局,形成100局的棋谱
#  下100局,拓展棋谱
def testWzTree():
'''
⽣成落⼦树
'''
tree = Tree()
for i in range(100):
WzOne( tree )
tree.printTree()
tree.save()
#读取树
print'------------------------------------------------'
tree2 = Tree()
tree2.load()
tree2.printTree()
pass
最多⽣成 24 个叶⼦(最低层)的树;也就是  24个棋谱
三:⽣成10x10 的五⼦对弈棋谱树
理论最⼤棋谱数 100 x 98 x 96x 94 x ......      (不考虑五⼦成线)貌似好⼏百亿试验了⼀下 7 x7 对弈五⼦棋,  10000 局,形成  195719 个节点的树
github :
待补充
数据结构和接⼝
本代码输出两个类:Node  和 Tree
节点保存的信息有两部分:
nodeInfo = [  nodeid,  level,  parentNodeid, [ node1,node2,node3 ]  ]
data = [data1, data2,data3,data3 ]    随应⽤定义
Node 输出接⼝:
create
setData(Data)
setParent(Node)
addSubNode(Node)
getSubNodeList()
def__init__(self):
def reset(self):
def load(self, filename = None ):
def save(self, filename = None ):
def printTree(self):
def getRootNode(self):
def getCurNode(self):
def addSubNodeToCur_Node(self, subNode, isMoveToSub = True ):
def addSubNodeToCur_Data(self,  data, NodeId = 0, isMoveToSub = True ): def moveToNode(self,nodeId ):
def moveToNode_byNode(self, node ):
def serachNodeId(self, thisNode, nodeId):
def moveUp(self):
代码:
gitHub:
代码:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: hylas zhang
import numpy as np;
import random
'''
Node  class
data
data: []
nodeinfo: id,  level, parentId, childrenIdList    [  0, 0, 0, []  ] childrenIdList  save to file  : [1,2,3,4]  ==>  1,2,3,4
export function:
create
setData(Data)
setParent(Node)
addSubNode(Node)
getSubNodeList()
in function:
'''
class Node():
def__init__(self, info=None, data=None, infodata = None ):
if( infodata != None ):
info = infodata[0:3] +[[]]
data = infodata[3:]
self.info = info
self.data = data
pass
self.data = ['']      #[ 0,0, '' ]  #times, wins, values
if( data != None ):
self.data = data
self.parent = None
self.children = []
pass
def setData(self,data):
self.data = data
def setParent(self, parentNode):
self.parent = parentNode
def addChild(self, childNode ):
self.children += [ childNode ]
def getSubNodeList(self):
def getDataInfo(self):
dataList = [deInfo[0],deInfo[1],deInfo[2]]  +self.data return dataList
def getData(self):
return self.data
def getInfo(self):
deInfo
def__repr__(self):
return"nodeInfo: {},  ".deInfo )
def__eq__(self, other):
selfVal = "{}".deInfo )
otherVal = "{}".deInfo)
if hash(selfVal) == hash(otherVal):
return True
return False
'''
Tree
export function:
5.loadFile
6.saveFile
7.addNewNodeInCurNode
7.获取usb最优节点
8.增加新节点
9.移动当前节点
内部:
'''
class Tree():
># 输出
def__init__(self):
<_Node = Node()
self.cur_Node = _Node
self.NodeCount = 1  # 节点+ 叶⼦数 + 1
pass
def reset(self):
self.cur_Node = _Node
pass
def load(self, filename = None ):
if(  filename == None ):
filename = './data.npy'
npData2 = np.load( filename )
lst2 = list()
for node in lst2:
info = node[0:3]
data = node[3:]
if( info[0] == 0  ):
continue
print'want to add:'
print node
if( info[2] == self.deInfo[0] ):
self.addSubNodeToCur_Data(data, NodeId = info[0] )
continue
#self.cur_Node
count = 10
while( info[2] != self.deInfo[0] ) :
ret = veUp()
if( ret == False ):
print'error ......'
continue
self.addSubNodeToCur_Data(data, NodeId = info[0])
self.printTree()
pass
def save(self, filename = None ):
if (filename == None):
filename = './data.npy'
nodeLst = self.fetchAllNode()
dataList =[]
for node in nodeLst :
print node
dataList += [ DataInfo() ]
#        Node.
pass
npData = np.array( dataList )
np.save(filename, npData )
'''
npData2 = np.load( './data.npy' )
lst2 = list()
print 'lst2:', lst2
'''
def printTree(self):
nodeLst = self.fetchAllNode()
for node in nodeLst :
DataInfo()
pass
def getRootNode(self):
_Node;
def getCurNode(self):
return self.cur_Node;
# nodeinfo: id, level, parentId, childrenIdList[0, 0, 0, []]
def addSubNodeToCur_Node(self, subNode, isMoveToSub = True ):
newNodeId = self.NodeCount
self.NodeCount += 1
self.cur_Node.children += [subNode]
self.deInfo[3] += [ newNodeId ]
subNode.parent = self.cur_Node
if( isMoveToSub ):
self.cur_Node = subNode
pass
def addSubNodeToCur_Data(self,  data, NodeId = 0, isMoveToSub = True ):        subNode = Node(data=data)
if(NodeId == 0 ):
newNodeId = self.NodeCount
else:
newNodeId = NodeId
self.NodeCount += 1
self.cur_Node.children += [subNode]
self.deInfo[3] += [ newNodeId ]
subNode.parent = self.cur_Node
#print 'addSubNodeToCur_Data, now in :', self.deInfo[0]
if( isMoveToSub ):
self.cur_Node = subNode
#print 'addSubNodeToCur_Data, now in :', self.deInfo[0]
def moveToNode(self,nodeId ):
node = self.serachNodeId( _Node, nodeId)

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。

发表评论