二叉树:深度优先遍历与广度优先遍历(及其Python实现)

二叉树:深度优先遍历与广度优先遍历(及其Python实现)

本问记录二叉树的深度优先遍历算法和广度优先遍历算法的特点及其python实现。

1 深度优先遍历

深度优先遍历算法包括先序遍历、中序遍历和后续遍历。

1.1 深度优先遍历顺序

我们根据下图只有3个节点的二叉树说明深度优先遍历顺序。
(各节点分别标上序号)
3_node

  1. 先序遍历:0→1→2
  2. 中序遍历:1→0→2
  3. 后序遍历:1→2→0

注意主要差别在于节点0在排序中的位置,节点1和节点2的相对位置是不变的(1在前,2在后)。

一般情况下的二叉树,如下图所示:
(各节点分别标上序号)
在这里插入图片描述
以先序遍历为例:
我们首先从最上面开始看,将0节点的左子树包含的节点当作一个整体(1、3、4、7、8、9),记为整体1;右子树包含的节点也当作一个整体(2、4、6),记为整体2;所以此时,先序遍历顺序为:

  • 0 → 整体1 → 整体2

但是整体1中还包含若干节点,所以继续分析整体1中的节点。
同理,从上往下分析,节点1左子树为一个整体(3、7、8),记为整体3;右子树为一个整体(4、9),记为整体4;所以此实,整体1中的先序遍历顺序为:

  • 1 → 整体3 → 整体4

同理,整体3包含若干节点,需要继续分析整体3(3、7、8)。
此时我们发现节点3左子树只有一个节点7,右子树只有一个节点8,所以整体3的先序遍历顺序为:

  • 3 → 7 → 8

于是,按照这个方法,我们能够推出整个二叉树的先序遍历顺序:

  • 0 → 1 → 3 → 7 → 8 → 4 → 9 → 2 → 5 → 6

同理,我们能推导出另外两种深度优先遍历的遍历顺序:

  1. 先序遍历:0 → 1 → 3 → 7 → 8 → 4 → 9 → 2 → 5 → 6
  2. 中序遍历:7 → 3 → 8 → 1 → 9 → 4 → 0 → 5 → 2 → 6
  3. 后序遍历:7 → 8 → 3 → 9 → 4 → 1 → 5 → 6 → 2 → 0

1.2 深度优先遍历Python实现

根据上述的遍历过程描述,我们可以看出这实际上是一个递归的过程,因此使用递归可以很简单地实现3种深度优先遍历。

首先定义节点和树的类并定义添加节点的方法,之后在二叉树类中定义先序遍历、中序遍历和后序遍历的方法。

# 节点类
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)
        cur_list = [self.root]
        if self.root is None:
            self.root = node
            return
        while True: 
            cur_node = cur_list.pop(0)
            if cur_node.lchild is None:
                cur_node.lchild = node
                return
            else:
                cur_list.append(cur_node.lchild)
            if cur_node.rchild is None:
                cur_node.rchild = node
                return
            else:
                cur_list.append(cur_node.rchild)
    # 先序遍历方法
    def preorder(self, cur_node):
        if cur_node is None:
            return
        print(cur_node.elem, end = " ")
        self.preorder(cur_node.lchild)
        self.preorder(cur_node.rchild)
    # 中序遍历方法
    def inorder(self, cur_node):
        if cur_node is None:
            return
        self.inorder(cur_node.lchild)
        print(cur_node.elem, end = " ")
        self.inorder(cur_node.rchild)
    # 后序遍历方法
    def postorder(self, cur_node):
        if cur_node is None:
            return
        self.postorder(cur_node.lchild)
        self.postorder(cur_node.rchild)
        print(cur_node.elem, end = " ")

测试:

tree = Tree()
for i in range(10)
    tree.add(i)
tree.preorder(tree.root)
print(" ")
tree.inorder(tree.root)
print(" ")
tree.postorder(tree.root)

结果:

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

2 广度优先遍历

2.1 广度优先遍历顺序

广度优先遍历的遍历顺序很简单:
从上至下,从左至右遍历。也就是说,同一层的节点从左至右遍历完了再到下一层,直至到空节点。
在这里插入图片描述
于是对于如图所示的二叉树:

  • 广度优先遍历:0 → 1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 → 9

2.2 广度优先遍历Python实现

广度优先遍历通过循环实现即可。
在前述代码中的二叉树类(Tree)中添加breadth_order方法:

    def breadth_order(self):
        queue = [self.root]
        if self.root is None:
            print("No node inside the tree.")
            return
        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)

测试:

tree = Tree()
for i in range(10)
    tree.add(i)
tree.breadth_order()

结果:

0 1 2 3 4 5 6 7 8 9

猜你喜欢

转载自blog.csdn.net/weixin_41670608/article/details/115032156