3-2-基础算法-查找算法2-树和二叉树查找(遍历:前序中序后序遍历,深度优先广度优先)
一、树
1、什么是树?
树状图是一种数据结构,它是由n(n>=1)个有限节点组成一个具有层次关系的集合。
把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。
它具有以下的特点:
每个节点有零个或多个子节点;
没有父节点的节点称为根节点;
每一个非根节点有且只有一个父节点;
除了根节点外,每个子节点可以分为多个不相交的子树;
几个概念
- 父节点,子节点: A和B
- 兄弟节点:D E J
- 根节点:A
- 叶节点: GI
几个概念
- 节点高度:节点到叶节点的最长路径(边数),这个图就是3,
- 节点深度:根节点到这节点所经历的边的个数,根节点的深度是0,
- 节点的层数:节点的深度 + 1
- 树高度:根节点的高度
二, 二叉树
树有有序树和无序树,我们只研究有序树中的二叉树,
1、什么是二叉树?
二叉树,就是度不差过2的树(节点最多有两个叉)
2,二叉树的分类:
1,完全二叉树:
叶节点只能出现在最下层和次下层,并且最下面一层的结点都集中在该层最左边的若干位置的二叉树
2,满二叉树
一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。
满二叉树一定是完全二叉树,但是完全二叉树不一定是满二叉树
3,平衡二叉树
4,二叉排序树
三、二叉树的存储方式
二叉树也可以使用顺序表进行存储,
不过树还是使用链表存储,就是连接两个节点,
常见的树应用的场景,html就是树的结构,
树的应用场景是非常的多的,
1、链式存储方式
a、二叉树的链式存储:将二叉树的节点定义为一个对象,节点之间通过类似链表的链接方式来连接。
b、节点定义
class BiTreeNode:
def init(self,data): #data就是传进去的节点的值
self.data = data
self.lchild = None
self.rchild = None
c、二叉树的遍历:
I 、先(前)序遍历:访问根结点的操作发生在遍历其左右子树之前
具体操作:若二叉树非空,则依次执行如下操作:
⑴ 访问根结点;
⑵ 遍历左子树;
⑶ 遍历右子树。
II、中序遍历:访问根结点的操作发生在遍历其左右子树之中(间)。
具体操作: 若二叉树非空,则依次执行如下操作:
⑴遍历左子树;
⑵访问根结点;
⑶遍历右子树。
III、后序遍历:访问根结点的操作发生在遍历其左右子树之后。
若二叉树非空,则依次执行如下操作:
⑴遍历左子树;
⑵遍历右子树;
⑶访问根结点。
IV、层次遍历
用一个队列保存被访问的当前节点的左右孩子以实现层序遍历。
二叉树的遍历代码
class Node(object):
"""节点类"""
def __init__(self, elem=-1, lchild=None, rchild=None):
self.elem = elem
self.lchild = lchild # 有两个子节点
self.rchild = rchild
class Tree(object):
"""树类"""
def __init__(self, root=None):
self.root = root
def add(self, elem):
"""为树添加节点"""
node = Node(elem)
#如果树是空的,则对根节点赋值
if self.root == None:
self.root = node
else:
queue = []
queue.append(self.root)
#对已有的节点进行层次遍历
while queue: # 结束的条件就是队列为空,
#弹出队列的第一个元素
cur = queue.pop(0)
if cur.lchild == None:
cur.lchild = node
return
elif cur.rchild == None:
cur.rchild = node
return
else:
#如果左右子树都不为空,加入队列继续判断
queue.append(cur.lchild)
queue.append(cur.rchild)
# 树的遍历
####################################################################
# 广度优先遍历
def breadth_travel(self):
"""利用队列实现树的层次遍历"""
if self.root == None:
return
queue = [self.root]
while queue:
node = queue.pop(0)
print(node.elem)
if node.lchild != None:
queue.append(node.lchild)
if node.rchild != None:
queue.append(node.rchild)
##################################################################
# 深度优先遍历
# 有三种方式
# 这个遍历的代码可以不用管,但是一定要会数,给你顺序,你能画出来一个二叉树,这个正推和逆推都要会
# 先序遍历,永远都是根节点优先,中左右
def preorder(self, root):
"""递归实现先序遍历"""
if root == None:
return
print(root.elem)
self.preorder(root.lchild)
self.preorder(root.rchild)
# 中序遍历: 左中右,
def inorder(self, root):
"""递归实现中序遍历"""
if root == None: # 这是递归的结束条件
return
self.inorder(root.lchild)
print(root.elem)
self.inorder(root.rchild)
# 后续遍历,左右中,
def postorder(self, root):
"""递归实现后续遍历"""
if root == None:
return
self.postorder(root.lchild)
self.postorder(root.rchild)
print(root.elem)
if __name__ == '__main__':
tree=Tree()
tree.add(1)
tree.add(2)
tree.add(3)
tree.add(4)
tree.add(5)
tree.breadth_travel()