二叉树的遍历
树的遍历是树的一种重要的运算。所谓遍历是指对树中所有结点的信息的访问,即依次对树中每个结点访问一次且仅访问一次,我们把这种对所有节点的访问称为遍历(traversal)。那么树的两种重要的遍历模式是深度优先遍历和广度优先遍历,深度优先一般用递归或者堆栈,广度优先一般用队列。一般情况下能用递归实现的算法大部分也能用堆栈来实现。
定义节点类
每个节点有三个属性:节点存放的元素item,左子树lchild,右子树rchild
class Node(object):
def __init__(self, item):
self.item = item
self.lchild = None
self.rchild = None
定义二叉树的类
class BinaryTree(object):
def __init__(self, node=None):
self.root = node
添加节点方法
def add(self, item):
"""添加节点"""
if self.root == None:
self.root = Node(item)
return
queue = []
# 尾部添加
queue.append(self.root)
while True:
# 头部取出
node = queue.pop(0)
if node.lchild == None:
node.lchild = Node(item)
return
else:
queue.append(node.lchild)
if node.rchild == None:
node.rchild = Node(item)
return
else:
queue.append(node.rchild)
广度优先遍历方法
def breadh_travel(self):
"""广度优先"""
if self.root == None:
return
queue = []
queue.append(self.root)
# 判断队列是否为空
while len(queue) > 0:
node = queue.pop(0)
print(node.item, end="")
# 判断左右子节点是否为空
if node.lchild is not None:
queue.append(node.lchild)
if node.rchild is not None:
queue.append(node.rchild)
深度优先遍历
1.先序遍历 在先序遍历中,我们先访问根节点,然后递归使用先序遍历访问左子树,再递归使用先序遍历访问右子树
根节点->左子树->右子树
def preorder(self, root):
"""递归实现先序遍历"""
if root == None:
return
print(root.item)
self.preorder(root.lchild)
self.preorder(root.rchild)
“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“””“”“”“”“”“”“”“”“”“”“”“”“”
"""非递归实现"""
if not root:
return
myStack = []
node = root
while myStack or node:
while node: # 从根节点开始,一直寻找他的左子树
print(node.item, end=''),
myStack.append(node)
node = node.lchild
node = myStack.pop() # while结束表示当前节点node为空,即前一个节点没有左子树了
node = node.rchild # 开始查看它的右子树
2.中序遍历 在中序遍历中,我们递归使用中序遍历访问左子树,然后访问根节点,最后再递归使用中序遍历访问右子树
左子树->根节点->右子树
def inorder(self, root):
"""递归实现中序遍历"""
if root == None:
return
self.inorder(root.lchild)
print(root.item)
self.inorder(root.rchild)
“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“
"""非递归实现"""
if not root:
return
myStack = []
node = root
while myStack or node: # 从根节点开始,一直寻找它的左子树
while node:
myStack.append(node)
node = node.lchild
node = myStack.pop()
print(node.item, end=''),
node = node.rchild
3.后序遍历 在后序遍历中,我们先递归使用后序遍历访问左子树和右子树,最后访问根节点
左子树->右子树->根节点
def postorder(self, root):
"""递归实现后续遍历"""
if root == None:
return
self.postorder(root.lchild)
self.postorder(root.rchild)
print(root.item)
“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“”“
"""非递归实现"""
# 先遍历根节点,再遍历右子树,最后是左子树,这样就可以转化为和先序遍历一个类型了,最后只把遍历结果逆序输出就OK了。
if not root:
return
myStack1 = []
myStack2 = []
node = root
while myStack1 or node:
while node:
myStack2.append(node)
myStack1.append(node)
node = node.rchild
node = myStack1.pop()
node = node.lchild
while myStack2:
print(myStack2.pop().item, end='')
测试
先序遍历: 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: 左 右 根
if __name__ == '__main__':
tree = BinaryTree()
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.breadh_travel() # 0123456789
# print()
# 深度优先遍历
tree.preorder_travel(tree.root) # 0137849256
print()
tree.inorder_travel(tree.root) # 7381940526
print()
tree.postorder_travel(tree.root) # 7839415620