二叉树的遍历分为深度优先遍历和广度优先遍历 。
深度优先遍历顾名思义是从树的一条分支走到底才进行回溯,深度优先遍历又分为前序遍历,中序遍历和后序遍历。
一棵二叉树由根结点、左子树和右子树三部分组成,若规定 D、L、R 分别代表遍历根结点、遍历左子树、遍历右子树。
DLR--前序遍历(根在前,从左往右,一棵树的根永远在左子树前面,左子树又永远在右子树前面 )
LDR--中序遍历(根在中,从左往右,一棵树的左子树永远在根前面,根永远在右子树前面)
LRD--后序遍历(根在后,从左往右,一棵树的左子树永远在右子树前面,右子树永远在根前面)
前序遍历代码实现:
def preorder(self, root):
if root is None:
return
print(root.elem)
self.preorder(root.left)
self.preorder(root.right)
中序遍历代码实现:
def inorder(self, root):
if root is None:
return
self.inorder(root.left)
print(root.elem)
self.inorder(root.right)
后序遍历代码实现:
def postorder(self, root):
if root is None:
return
self.postorder(root.left)
self.postorder(root.right)
print(root.elem)
这三种遍历方式都用了递归的思想
广度优先遍历又叫宽度优先遍历,与深度优先遍历不同,广度优先遍历是一层一层的遍历二叉树,每一层所有的结点都遍历完后才会遍历下一层的结点。
代码实现:
def levelorder(self, root):
if root is None:
return
queue = []
queue.append(root)
while queue:
cur = queue.pop(0)
print(cur.data)
if cur.left is not None:
queue.append(cur.left)
if cur.right is not None:
queue.append(cur.right)
注:以上的函数都是在树类中定义的函数
宽度优先遍历的代码解释:
首先,设置了一个参数root,root表示从当前结点开始进行宽度优先遍历,这个结点可以是根结点也可以不是根结点,一般情况下都设置为根结点,然后判断这个树是不是空树,如果是空树就不用遍历了直接return结束,若不是空树,创建一个队列,利用队列一端进另一端出的特点,队列可以很好的储存树中每一层的结点的值,然后再按顺序释放出来,这一思路就实现了宽度优先遍历的要求,后面需要做的就是将二叉树中的结点一个个的按顺序入队然后再出队。while queue:如果队列不为空,就继续循环
# 使用结点和引用来表示树
class Node(object):
def __init__(self, dat=-1):
self.left = None
self.right = None
self.data = dat
class Tree(object):
# 树类
def __init__(self):
self.root = Node()
'''用递归的方式实现深度优先遍历。深度优先遍历包含先序遍历
中序遍历和后序遍历'''
# 先序遍历
def preorder(self, root):
if root is None:
return
print(root.data)
self.preorder(root.left)
self.preorder(root.right)
# 中序遍历
def inorder(self, root):
if root is None:
return
self.inorder(root.left)
print(root.data)
self.inorder(root.right)
# 后序遍历
def postorder(self, root):
if root is None:
return
self.postorder(root.left)
self.postorder(root.right)
print(root.data)
# 添加结点
'''在树中指定位置添加结点,需要对树进行遍历,而且没有规律,
这个地方添加结点的方法是一层一层的添加,从左往右添加'''
def add(self, data):
# 为所需要添加的数据创建一个结点类
node = Node(data)
# 如果树为空,就为根结点赋值
if self.root.data == -1:
self.root = node
else:
queue = []
new_node = self.root
queue.append(new_node)
while queue:
new_node = queue.pop(0)
if new_node.left is None:
new_node.left = node
return
elif new_node.right is None:
new_node.right = node
return
else:
queue.append(new_node.left)
queue.append(new_node.right)
# 宽度优先遍历
def levelorder(self, root):
if root is None:
return
queue = []
queue.append(root)
while queue:
cur = queue.pop(0)
print(cur.data)
if cur.left is not None:
queue.append(cur.left)
if cur.right is not None:
queue.append(cur.right)
if __name__ == '__main__':
# 主函数
datas = [1, 2, 3, 4, 5, 6, 7, 8, 9]
tree = Tree() # 新建一个树对象
for data in datas:
tree.add(data) # 逐个加入树的节点
print('递归实现前序遍历:')
tree.levelorder(tree.root)
对于将Node类中的dat=-1,将dat的值默认为-1,这样做方便了后面的结点创造,就可一创造一个不用赋值的结点出来,方面程序的继续写下去。
实验结果: