前言
以下是花圃在学习Python的数据结构与算法的一些要点内容笔记。
一、树
1.概念
树(tree)本身就是一种抽象的数据结构(ADT),树是一种非线性的数据结构,它是由n (n>=0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。特点是:
每个节点都有零个或者多个子节点
没有父节点的节点称之为根节点
每一个非根节点有且只有一个父节点
除了根节点之外,每个子结点可以分出多个不相交的子树
2.术语
节点的度:一个节点含有子树的个数(实际上来说就是一个节点的子节点的个数有多少)
树的度:一棵树之中最大的节点的度称之为树的度
叶节点:度为零,也就是不再有子节点的节点
父节点:有一个节点含有子节点,该节点称此节点的父节点
子节点:一个子树含有的根节点称之为该节的子节点
兄弟节点:具有相同父节点的节点
节点的层次:从根开始,根为第一层,根的子节点称之为第二层,根的子节点的子节点称之为第三层依次类推
树的高度或深度:树中节点最大的层次
堂兄弟节点:上上节点同
节点的祖先:该节点一直到根的线路上的所有节点
子孙:以某一节点为根的子树的任意节点
森林:互不相交的多棵树称森林
3.种类
(1)无序树
(2)有序树
Ⅰ二叉树
①完全二叉树
②满二叉树
③平衡二叉树
④排序二叉树
Ⅱ霍夫曼树
ⅢB树
4.数据存储
顺序存储
链式存储
二、二叉树
1.概念、性质
二叉树的概念其实就是对于每一个节点最多有两个子节点
二叉树的性质:
①在深度为K的二叉树中,最多存在2^k -1个节点
②在第K层中,该层最多有2^(k-1)个节点
③假设树结构中边的个数为x,树节点的个数为n,他们之间的关系是x=n-1,通过这个可以推出,度为2的节点(N2)和度为0的节点(N0)之间的关系:N0=N2+1
2.实现
**广度优先遍历:**广度优先遍历实际上是在同层次之间开展的,利用的是队列的概念,思路是这样的,首先我队列中去添加我的根节点地址,通过弹出的方式取出此时元素(那一段是头自己定,顺序不要乱),判断他的左孩子是否为空,为空直接添加元素到这个位置然后直接return去返回结束(因为后面涉及判断右孩子),不是空将左孩子追加到我的队列中,注意从一开始弹出的另一端去追加,比如弹出头部,那你就要追加在尾部,不为空(遍历的话,就需要在弹出的时候打印出来);判断右孩子是否为空,为空直接挂元素,return返回,不为空就直接在队列中追加元素。整个过程直到我的队列为空,结束。
# 定义节点:
class Node(object):
def __init__(self,item):
self.elem=item
self.rchild=None
self.lchild=None
pass
pass
# 定义连接关系:
class Tree(object):
def __init__(self):
self.__root=None
pass
def add(self,item):
node=Node(item)
if self.__root is None:
self.__root=node
return
queue=[self.__root]
while queue:
cur_node=queue.pop(0)
if cur_node.lchild is None:
cur_node.lchild=node
return
else:
queue.append(cur_node.lchild)
pass
if cur_node.rchild is None:
cur_node.rchild=node
return
else:
queue.append(cur_node.rchild)
pass
pass
def bread_travel(self):
queue=[self.__root]
while queue:
cur_node=queue.pop(0)
print(cur_node.elem)
if cur_node.lchild is not None:
queue.append(cur_node.lchild)
pass
if cur_node.rchild is not None:
queue.append(cur_node.rchild)
pass
pass
pass
pass
if __name__=="__main__":
tree=Tree()
tree.add(1)
tree.add(2)
tree.add(3)
tree.bread_travel()
深度优先遍历:
先序遍历:根节点–》左树–》右树
中序遍历:左树–》根节点–》右树
后序遍历:左树–》右树–》根节点
【以上三种起始先中后看的是根节点的位置】
# 定义节点:
class Node(object):
def __init__(self,item):
self.elem=item
self.rchild=None
self.lchild=None
pass
pass
# 定义连接关系:
class Tree(object):
def __init__(self,root=None):
self.__root=root
pass
def add(self,item):
node=Node(item)
if self.__root is None:
self.__root=node
return
queue=[self.__root]
while queue:
cur_node=queue.pop(0)
if cur_node.lchild is None:
cur_node.lchild=node
return
else:
queue.append(cur_node.lchild)
pass
if cur_node.rchild is None:
cur_node.rchild=node
return
else:
queue.append(cur_node.rchild)
pass
pass
def bread_travel(self):
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)
pass
if cur_node.rchild is not None:
queue.append(cur_node.rchild)
pass
pass
pass
def deep_preorder(self,node):
if node is None:
return
print(node.elem,end=" ")
self.deep_preorder(node.lchild)
self.deep_preorder(node.rchild)
pass
def deep_midorder(self,node):
if node is None:
return
self.deep_midorder(node.lchild)
print(node.elem,end=" ")
self.deep_midorder(node.rchild)
pass
def deep_postorder(self,node):
if node is None:
return
self.deep_postorder(node.lchild)
self.deep_postorder(node.rchild)
print(node.elem,end=" ")
pass
pass
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.bread_travel()
print()
tree.deep_preorder(tree._Tree__root)
print()
tree.deep_midorder(tree._Tree__root)
print()
tree.deep_postorder(tree._Tree__root)
0 1 2 3 4 5 6 7 8 9
0 1 3 7 8 4 9 2 5 6
7 3 8 1 9 4 0 5 2 6
7 8 3 9 4 1 5 6 2 0
如何通过遍历去确定一棵树:
要确定一棵树,一定要有中序,无论是先序+中序,还是中序+后序。原因在于中序是左根右,根将左右分开。
例如:先序+中序
0 1 3 7 8 4 9 2 5 6
7 3 8 1 9 4 0 5 2 6
先序是 根 左 右
中序是 左 根 右
【0】 1 3 7 8 4 9 2 5 6 0就是根节点,其余部分是左树+右树
7 3 8 1 9 4 【0】 5 2 6 0左侧就是左树,右侧就是右树
所以
【0 】1 3 7 8 4 9 2 5 6 ------》【0】 【1 3 7 8 4 9】 【2 5 6】
所以
左树的根就是1,右树的根就是2
所以
【7 3 8 【1】9 4 】【 0】 【5【2】 6】
所以对于中序的——9 4和先序的——49——就是4为根,9为左孩子
即