数的概念
模拟具有树状结构性质的数据集合。
-
每个节点有零个或多个子节点
-
没有父节点的节点称为根节点
-
每一个非跟节点有且只有一个父节点
-
除了根节点外,每个子节点可以分为多个不相交的子树
树的属于
-
节点的度:一个节点含有的子树的个数称为该节点的度。
-
树的毒:最大的节点称为树的度。
-
终端节点:度为零的节点。
-
父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点。
-
子节点:一个节点含有的子树的根节点称为该节点的子节点
-
兄弟节点:具有相同父节点的子节点
-
节点的层次:根为第一次,根的子节点为第二层,以此类推。
-
树的高度和深度:树中节点的最大层次
-
堂兄弟节点: 父节点在同一层的节点
-
节点的祖先:从根到该节点所经分支的所有节点
-
子孙:以某节点为根的子树中任一节点
-
森林:互不相交的树的集合成为森林
分类
-
有序树:树中任意节点无顺序关系
-
有序树:数值任意节点的子节点之间有顺序关系
二叉树
每个节点最多含有两个子树的树
-
完全二叉树: 对于一棵二叉树,假设其深度为d,除了第d层外,其他各层的节点数目均已达最大值。且第d层所有节点从左向右连续地紧密排列,这样的二叉树被称为完全二叉树,其中满二叉树的定义是所有叶节点都在最底层的完全二叉树
-
平衡二叉树:当且仅有任何节点的两棵子树的高度差不大于一的二叉树
-
排序二叉树
霍夫曼树
带权路径最短的二叉树称为霍夫曼树
B树
一种对读写操作进行优化的自平衡的二叉查找树,能够保持数据有序,拥有多于两个子树。
-
平衡二叉树:当且仅有任何节点的两棵子树的高度差不大于一的二叉树
-
排序二叉树
霍夫曼树
带权路径最短的二叉树称为霍夫曼树
B树
一种对读写操作进行优化的自平衡的二叉查找树,能够保持数据有序,拥有多于两个子树。
树的存储与表述
-
顺序存储,用数组
-
链式存储,指针域指针个数不稳定。
常见的树的应用
-
html
-
mysql
-
文件目录
-
路由协议
二叉树
性质
-
第i层有2(i-1)个节点
-
深度为k的二叉树至多有2^k-1个节点。
-
如果节点为N0,度数为2的节点为N2,N0=N2+1
-
具有n个节点的完全二叉树深度为log(n+1)
class Node(object):
def __init__(self,item):
self.elem=item
self.lchild=None
self.rchild=None
class Tree(object):
def __init__(self):
self.root=None
def add(self,item):
node=Node(item)
queue=[]
queue.append(self.root)
while len(queue)>0: #只要队列不为空,就一直循环遍历
cur_node=queue.pop(0)
if cur_node.lchild is None: #如果左边为空
cur_node.lchild=node
return
else:
queue.append(cur_node.lchild)
if cur_node.rchild is None:
cur_node.rchild=node
return
else:
queue.append(cur_node.rchild)
tree=Tree()
class Node(object):
def __init__(self,item):
self.elem=item
self.lchild=None
self.rchild=None
class Tree(object):
def __init__(self):
self.root=None
def add(self,item):
node=Node(item)
if self.root is None:
self.root=node
return
queue=[]
queue.append(self.root)
while len(queue)>0: #只要队列不为空,就一直循环遍历
cur_node=queue.pop(0)
if cur_node.lchild is None: #如果左边为空
cur_node.lchild=node
return
else:
queue.append(cur_node.lchild)
if cur_node.rchild is None:
cur_node.rchild=node
return
else:
queue.append(cur_node.rchild)
def breadth_travel(self): #广度遍历:一层一层的遍历
if self.root is None:
return
queue=[self.root]
while queue:
cur_node=queue.pop(0)
print(cur_node.elem,end="")
if cur_node.lchild is not None:
queue.append(cur_node.lchild)
if cur_node.rchild is not None:
queue.append(cur_node.rchild)
def preorder(self,node):
#根左右 先序遍历
if node is None:
return
print(node.elem,end="")
self.preorder(node.lchild)
self.preorder(node.rchild)
def inorder(self,node):
#左根右 中序遍历
if node is None:
return
self.inorder(node.lchild)
print(node.elem,end="")
self.inorder(node.rchild)
def postorder(self,node):
#左右根 后续遍历
if node is None:
return
self.postorder(node.lchild)
self.postorder(node.rchild)
print(node.elem, end="")
if __name__=="__main__":
tree=Tree()
tree.add(0)
tree.add(1)
tree.add(2)
tree.add(3)
tree.add(4)
tree.add(5)
tree.add(6)
tree.add(7)
tree.add(8)
tree.add(9)
tree.breadth_travel()
print("\n")
tree.preorder(tree.root) #顺着树的根节点
print("\n")
tree.inorder(tree.root)
print("\n")
tree.postorder(tree.root)
用先序去判断根,在中序中定位到根的位置,将左右分开,再在先序中判断第二层的根,依此类推,将整个树画出来。