python--数据结构--二叉树

1. 二叉树结构可视化

思路
为了避免重合,二叉树左右子树的距离是关键
让每一个节点占用一个列空间,这样就不会重合了
所以
左节点与父节点在X轴上的距离为 左节点 的 右子树宽度+1 乘以一个水平距离常数
右节点与父节点在X轴上的距离为 右节点 的 左子树宽度+1 乘以一个水平距离常数

每当画好一个节点点,确定其左右孩子在X轴上的距离,再画这个节点连接孩子的边

from matplotlib import pyplot as plt


class Node(object):
    """二叉树节点,节点有左右孩子,左孩子left_child,右孩子right_chile"""
    def __init__(self, value):
        """
        初始化节点
        :param value: 节点中所保存的值
        """
        self.left_child = None  # 左孩子
        self.right_child = None  # 右孩子
        self.value = value

    def __str__(self):
        return self.value


class BiTree(object):
    def __init__(self, d_hor=4, d_vec=8, radius=1.5, figsize =(11, 9)):
        """
            对所展示二叉树的一些元素参数的设置
            :param d_hor: 节点与节点的水平距离
            :param d_vec: 节点与节点的垂直距离
            :param radius: 节点的半径
            :param radius: 画布大小,用一个元祖表示画布width和high,单位为inch
            """
        self.root = None
        self.d_hor = d_hor
        self.d_vec = d_vec
        self.radius = radius
        self.figsize = figsize

    def get_left_width(self, root):
        """获得根左边宽度,也是根的左子孙节点数"""
        return self.get_width(root.left_child)

    def get_right_width(self, root):
        """获得根右边宽度,也是根的右子孙节点数"""
        return self.get_width(root.right_child)

    def get_width(self, root):
        """获得树的宽度,也是该树的节点数"""
        if root:
            return self.get_width(root.left_child) + 1 + self.get_width(root.right_child)
        else:
            return 0

    def get_height(self, root):
        """获得二叉树的高度"""
        if root:
            return max(self.get_height(root.left_child), self.get_height(root.right_child)) + 1
        else:
            return 0

    def get_w_h(self, root):
        """获得树的宽度和高度"""
        w = self.get_width(root)
        h = self.get_height(root)
        return w, h

    def __draw_a_node(self, x, y, value, ax):
        """画一个节点"""
        c_node = plt.Circle((x, y), radius=self.radius, color="#65DDFF")
        ax.add_patch(c_node)
        plt.text(x, y, value, ha='center', va='center', fontsize=25, )

    def __draw_a_edge(self, x1, y1, x2, y2):
        """画一条边"""
        x = (x1, x2)
        y = (y1, y2)
        plt.plot(x, y, 'g-')

    def __create_win(self, root):
        """创建窗口"""
        # WEIGHT: 树宽,HEIGHT: 树高
        WEIGHT, HEIGHT = self.get_w_h(root)
        # WEIGHT:树宽 + 1
        WEIGHT = (WEIGHT+1)*self.d_hor
        # HEIGHT = 树高+1
        HEIGHT = (HEIGHT+1)*self.d_vec
        # print(WEIGHT, HEIGHT)

        # fig = plt.figure(figsize=(a, b), dpi=dpi)
        # 设置图形的大小,a 为图形的宽, b 为图形的高,单位为英寸
        # dpi 为设置图形每英寸(inch)的点数
        # 1点(英美点)=0.3527毫米=1/72英寸(Office里面的点)。
        # 线条,标记,文本等大多数元素都有以磅(point即点)为单位的大小。因1inch = 72point,则72dp/inch=1dp/point、144dp/inch=2dp/point
        fig = plt.figure(figsize=self.figsize)
        ax = fig.add_subplot(111)  # 表示整个figure分成1行1列,共1个子图,这里子图在第一行第一列

        plt.xlim(0, WEIGHT)  # 设定x座标轴的范围,当前axes上的座标轴。
        plt.ylim(0, HEIGHT)  # 设定y座标轴的范围,当前axes上的座标轴。
        x = (self.get_left_width(root) + 1) * self.d_hor  # x, y 是第一个要绘制的节点坐标,由其左子树宽度决定
        y = HEIGHT - self.d_vec
        return fig, ax, x, y

    def __print_tree_by_preorder(self, root, x, y, ax):
        """通过先序遍历打印二叉树"""

        if not root:
            # 根节点为空返回
            return

        # 画节点
        self.__draw_a_node(x, y, root.value, ax)

        # 画左右分支
        lx = rx = 0
        ly = ry = y - self.d_vec
        if root.left_child:
            lx = x - self.d_hor * (self.get_right_width(root.left_child) + 1)   # x-左子树的右边宽度
            self.__draw_a_edge(x, y, lx, ly)
            # print(root.left_child, (lx, ly))
        if root.right_child:
            rx = x + self.d_hor * (self.get_left_width(root.right_child) + 1)   # x-右子树的左边宽度
            # print(root.right_child, (rx, ry))
            self.__draw_a_edge(x, y, rx, ry)

        # 递归打印
        self.__print_tree_by_preorder(root.left_child, lx, ly, ax)
        self.__print_tree_by_preorder(root.right_child, rx, ry, ax)

    def show_BiTree(self):
        """可视化二叉树"""
        _, ax, x, y = self.__create_win(self.root)
        self.__print_tree_by_preorder(self.root, x, y, ax)
        plt.show()

    def __create_tree(self):
        value = input("输入节点数据:").strip()
        if value:
            node = Node(value)
            node.left_child = self.__create_tree()
            node.right_child = self.__create_tree()
            return node
        else:
            return None

    def create_tree(self):
        self.root = self.__create_tree()


if __name__ == '__main__':
    bi_tree = BiTree()
    bi_tree.create_tree()
    print("+++++++++++++++++++")
    bi_tree.show_BiTree()

测试

输入节点数据:5
输入节点数据:6
输入节点数据:
输入节点数据:2
输入节点数据:
输入节点数据:
输入节点数据:1
输入节点数据:
输入节点数据:3
输入节点数据:0
输入节点数据:
输入节点数据:
输入节点数据:
+++++++++++++++++++

Process finished with exit code 0

在这里插入图片描述
[参考博客]
用pyplot打印二叉树,实现二叉树的可视化

2. 二叉树中一些其它常用方法

# BiTree
from matplotlib import pyplot as plt
from collections import deque


class Node(object):
    """二叉树节点,节点有左右孩子,左孩子left_child,右孩子right_chile"""
    def __init__(self, value):
        """
        初始化节点
        :param value: 节点中所保存的值
        """
        self.left_child = None  # 左孩子
        self.right_child = None  # 右孩子
        self.value = value

    def __str__(self):
        return self.value


class BiTree(object):
    """二叉树及其常用方法"""
    def __init__(self, d_hor=4, d_vec=8, radius=1.5, figsize =(11, 9)):
        """
            对所展示二叉树的一些元素参数的设置
            :param d_hor: 节点与节点的水平距离
            :param d_vec: 节点与节点的垂直距离
            :param radius: 节点的半径
            :param radius: 画布大小,用一个元祖表示画布width和high,单位为inch
            """
        self.root = None
        self.d_hor = d_hor
        self.d_vec = d_vec
        self.radius = radius
        self.figsize = figsize

    def get_left_width(self, root):
        """获得根左边宽度,也是根的左子孙节点数"""
        return self.get_width(root.left_child)

    def get_right_width(self, root):
        """获得根右边宽度,也是根的右子孙节点数"""
        return self.get_width(root.right_child)

    def get_width(self, root):
        """获得树的宽度,也是该树的节点数。使用的是中序遍历方式"""
        if root:
            return self.get_width(root.left_child) + 1 + self.get_width(root.right_child)
        else:
            return 0

    def get_height(self, root):
        """获得二叉树的高度, 使用后序遍历"""
        if root:
            return max(self.get_height(root.left_child), self.get_height(root.right_child)) + 1
        else:
            return 0

    def get_w_h(self, root):
        """获得树的宽度和高度"""
        w = self.get_width(root)
        h = self.get_height(root)
        return w, h

    def __draw_a_node(self, x, y, value, ax):
        """画一个节点"""
        c_node = plt.Circle((x, y), radius=self.radius, color="#65DDFF")
        ax.add_patch(c_node)
        plt.text(x, y, value, ha='center', va='center', fontsize=25, )

    def __draw_a_edge(self, x1, y1, x2, y2):
        """画一条边"""
        x = (x1, x2)
        y = (y1, y2)
        plt.plot(x, y, 'g-')

    def __create_win(self, root):
        """创建窗口"""
        # WEIGHT: 树宽,HEIGHT: 树高
        WEIGHT, HEIGHT = self.get_w_h(root)
        # WEIGHT:树宽 + 1
        WEIGHT = (WEIGHT+1)*self.d_hor
        # HEIGHT = 树高+1
        HEIGHT = (HEIGHT+1)*self.d_vec
        # print(WEIGHT, HEIGHT)

        # fig = plt.figure(figsize=(a, b), dpi=dpi)
        # 设置图形的大小,a 为图形的宽, b 为图形的高,单位为英寸
        # dpi 为设置图形每英寸(inch)的点数
        # 1点(英美点)=0.3527毫米=1/72英寸(Office里面的点)。
        # 线条,标记,文本等大多数元素都有以磅(point即点)为单位的大小。因1inch = 72point,则72dp/inch=1dp/point、144dp/inch=2dp/point
        fig = plt.figure(figsize=self.figsize)
        ax = fig.add_subplot(111)  # 表示整个figure分成1行1列,共1个子图,这里子图在第一行第一列

        plt.xlim(0, WEIGHT)  # 设定x座标轴的范围,当前axes上的座标轴。
        plt.ylim(0, HEIGHT)  # 设定y座标轴的范围,当前axes上的座标轴。
        x = (self.get_left_width(root) + 1) * self.d_hor  # x, y 是第一个要绘制的节点坐标,由其左子树宽度决定
        y = HEIGHT - self.d_vec
        return fig, ax, x, y

    def __print_tree_by_preorder(self, root, x, y, ax):
        """通过先序遍历打印二叉树"""

        if not root:
            # 根节点为空返回
            return

        # 画节点
        self.__draw_a_node(x, y, root.value, ax)

        # 画左右分支
        lx = rx = 0
        ly = ry = y - self.d_vec
        if root.left_child:
            lx = x - self.d_hor * (self.get_right_width(root.left_child) + 1)   # x-左子树的右边宽度
            self.__draw_a_edge(x, y, lx, ly)
            # print(root.left_child, (lx, ly))
        if root.right_child:
            rx = x + self.d_hor * (self.get_left_width(root.right_child) + 1)   # x-右子树的左边宽度
            # print(root.right_child, (rx, ry))
            self.__draw_a_edge(x, y, rx, ry)

        # 递归打印
        self.__print_tree_by_preorder(root.left_child, lx, ly, ax)
        self.__print_tree_by_preorder(root.right_child, rx, ry, ax)

    def show_BiTree_1(self):
        """可视化二叉树"""
        _, ax, x, y = self.__create_win(self.root)
        self.__print_tree_by_preorder(self.root, x, y, ax)
        plt.show()

    def show_BiTree_2(self):
        """采用逆中序方法+矩阵转置"""
        def inner_func(root, layer):
            if root:
                inner_func(root.left_child, layer + 1)
                print(f"{' ' * layer}{root.value}")
                inner_func(root.right_child, layer + 1)
        return inner_func(self.root, 1)

    def __create_tree(self):
        value = input("输入节点数据:").strip()
        if value:
            node = Node(value)
            node.left_child = self.__create_tree()
            node.right_child = self.__create_tree()
            return node
        else:
            return None

    def create_tree(self):
        """先序方式创建二叉树"""
        self.root = self.__create_tree()

    def create_tree_extension(self, seq):
        """
        利用扩展先序遍历序列创建二叉树
        扩展先序遍历序列:AB.DF..G..C.E.H..
        创建过程:首先读入当前根节点的数据,如果是“.”则将当前树根置为空,否则申请一个新节点,存入当前根节点的数据,
                分别用当前根节点的左子域和右子域进行递归调用,创建左右子树。
        :param seq: 扩展先序遍历序列
        :return: 创建好的一棵树
        """
        if seq:
            index = 0

            def inner_function():
                nonlocal index
                try:
                    if seq[index] == ".":
                        index += 1
                        return
                    else:
                        node = Node(seq[index])
                        index += 1
                        node.left_child = inner_function()
                        node.right_child = inner_function()
                        return node
                except IndexError as e:
                    pass
            self.root = inner_function()

    def pre_order_1(self):
        """先序递归遍历"""
        trav_seq = deque()

        def inner_func(root):
            if root:
                nonlocal trav_seq
                trav_seq.append(root.value)
                inner_func(root.left_child)
                inner_func(root.right_child)
            else:
                return

        inner_func(self.root)
        return trav_seq

    def in_order_1(self):
        """中序递归遍历,方法1"""
        trav_seq = deque()

        def inner_func(root):
            if root:
                nonlocal trav_seq
                inner_func(root.left_child)
                trav_seq.append(root.value)
                inner_func(root.right_child)
            else:
                return

        inner_func(self.root)
        return trav_seq

    def post_order_1(self):
        """后序递归遍历"""
        trav_seq = deque()

        def inner_func(root):
            if root:
                nonlocal trav_seq
                inner_func(root.left_child)
                inner_func(root.right_child)
                trav_seq.append(root.value)
            else:
                return

        inner_func(self.root)
        return trav_seq

    def pre_order_2(self):
        """
        先序非递归遍历,方法2
        算法思想:
            从根节点开始,只要当前节点存在,或者栈不空,则重复下面的操作。
            (1)如果当前根节点存在,则访问当前结点并遍历左子树
            (2)否则退栈,然后遍历右子树
        算法时间复杂度:
                对有n个结点二叉树,该算法每循环一次,p指向一个节点或空(无左孩子或无右孩子的节点的空链域),
            因此指向空的次数为n+1,n为节点个数,故循环次数为n+(n+1)=2n+1,因此算法的复杂度为O(n).
        空间复杂度:
                所需栈的空间最多等于二叉树K乘以每个节点所需空间数,记作O(K)
        总结:入栈顺序是先序,在入栈前访问结点,访问后将当前结点设置为当前结点的左孩子
        :return: 先序遍历序列
        """
        def inner_func(root):
            from collections import deque
            temp_stack = deque()
            trav_seq = deque()  # 用于存放访问过的结点
            p = root  # 当前结点
            while p or temp_stack:
                if p:
                    trav_seq.append(p.value)  # 访问当前结点
                    temp_stack.append(p)  # 将当前结点入栈
                    p = p.left_child  # 当前结点更新为当前结点的左孩子
                else:
                    p = temp_stack.pop()  # 将栈顶结点出栈
                    p = p.right_child  # 将当前结点设置为栈顶结点的右孩子,为了将栈顶结点右子树入栈
            return trav_seq
        return inner_func(self.root)

    def in_order_2(self):
        """
        中序非递归遍历,方法2
        算法思想:
            从根节点开始,只要当前节点存在,或者栈不空,则重复下面的操作。
            (1)如果当前根节点存在,则进展并遍历左子树
            (2)否则退栈并访问,然后遍历右子树
        算法时间复杂度:
                对有n个结点二叉树,该算法每循环一次,p指向一个节点或空(无左孩子或无右孩子的节点的空链域),
            因此指向空的次数为n+1,n为节点个数,故循环次数为n+(n+1)=2n+1,因此算法的复杂度为O(n).
        空间复杂度:
                所需栈的空间最多等于二叉树K乘以每个节点所需空间数,记作O(K)
        总结:入栈顺序是先序,在出栈时立即访问结点,访问后将当前结点设置为当前结点的右孩子
        :return: 中序遍历序列
        """
        def inner_func(root):
            from collections import deque
            temp_stack = deque()
            trav_seq = deque()  # 用于存放访问过的结点
            p = root  # 当前结点
            while p or temp_stack:
                if p:
                    temp_stack.append(p)  # 将当前结点入栈
                    p = p.left_child  # 当前结点更新为当前结点的左孩子
                else:
                    p = temp_stack.pop()  # 将栈顶结点出栈,获取当前结点
                    # print(root.value)
                    trav_seq.append(p.value)  # 访问栈顶结点
                    p = p.right_child  # 将当前结点设置为栈顶结点的右孩子,为了将栈顶结点右子树入栈
            return trav_seq
        return inner_func(self.root)

    def post_order_2(self):
        """
        后序非递归遍历,方法2
        算法思想:
            从根节点开始,只要当前结点存在,或者栈不空,则重复下面的操作:
                (1) 从当前结点开始,进栈并遍历左子树,直到左子树为空。
                (2) 如果栈顶结点的右子树为空,或者栈顶结点的右孩子为刚被访问过的结点(表明栈顶结点的右子树已被访问过),
                    则退栈并访问,然后将当前结点指针置为空。
                (3) 否则,遍历右子树 。
        总结:入栈顺序是先序,通过对访问条件的是否满足的判断使得访问顺序是后序。
        :return: 后序遍历序列
        """
        def inner_func(root):
            from collections import deque
            temp_stack = deque()
            trav_seq = deque()  # 用于存放访问过的结点
            temp_root = None  # 临时结点,用于保存刚刚访问过的节点
            p = root  # 当前结点
            while p or temp_stack:
                if p:
                    temp_stack.append(p)  # 将当前结点入栈
                    p = p.left_child  # 当前结点更新为当前结点的左孩子
                else:
                    p = temp_stack.pop()  # 将栈顶结点出栈,获取当前结点
                    temp_stack.append(p)  # 由于此时并不是真正的出栈只是为了获取栈顶结点,因此还需再次入栈
                    if not p.right_child or p.right_child is temp_root:  # 满足两个条件中任意一个,则访问栈顶结点
                        trav_seq.append(p.value)  # 访问栈顶结点
                        temp_stack.pop()  # 栈顶结点已被访问,此时需要出栈
                        temp_root = p  # 将刚访问过的栈顶结点保存起来,以便下一次用于判断
                        p = None  # 将当前结点设置为空,避免对当前结点的左子树再次入栈
                    else:
                        p = p.right_child  # 将当前结点设置为当前结点的右孩子,为了将当前结点右子树入栈
            return trav_seq
        return inner_func(self.root)

    def leaf_number_1(self):
        """获取叶子节点数目,通过后序遍历方法一"""
        leaf_number_ = 0

        def inner_func(root):
            if root:
                nonlocal leaf_number_
                inner_func(root.left_child)
                inner_func(root.right_child)
                if not root.leaf_child and not root.right_child:
                    leaf_number_ += 1
        inner_func(self.root)
        return leaf_number_

    def leaf_number_2(self):
        """
        获取叶子节点数目,通过后序遍历方法二
        对比leaf_number_1,去除了if 嵌套
        """

        def inner_func(root):
            if not root:
                return 0
            elif not root.left_child and not root.right_child:
                return 1
            else:
                return inner_func(root.left_child) + inner_func(root.right_child)
        return inner_func(self.root)

    def get_high_pre(self):
        """
        获取树的高度,先序遍历方法
        精髓在于树的高度的迭代更新
        :return: 树的高度
        """
        deepth = 0  # 临时保存上一个节点的层级

        def inner_func(root, high):
            """
            :param root: 当前根节点,假设当前根节点是存在的
            :param high: 表示当前根节点root的层级
            :return:
            """
            if not root:  # 判断当前根节点是否真的存在
                return
            else:
                nonlocal deepth
                if deepth < high:
                    deepth = high
                else:
                    pass
                inner_func(root.left_child, high+1)
                inner_func(root.right_child, high+1)
        inner_func(self.root, 1)
        return deepth

    def get_high_in(self):
        """
        获取树的深度,中序遍历方法
        精髓在于树的高度的迭代更新
        :return: 树的高度
        """
        deepth = 0  # 临时保存上一个节点的层级

        def inner_func(root, high):
            """
            :param root: 当前根节点,假设当前根节点是存在的
            :param high: 表示当前根节点root的层级
            :return: None
            """
            if root:  # 判断当前根节点是否真的存在
                nonlocal deepth
                inner_func(root.left_child, high+1)
                if deepth < high:
                    deepth = high
                inner_func(root.right_child, high+1)

        inner_func(self.root, 1)
        return deepth

    def get_high_post_1(self):
        """
        获取树的高度,后序遍历方法1
        精髓在于树的高度的迭代更新
        :return: 树的高度
        """
        deepth = 0  # 临时保存上一个节点的层级

        def inner_func(root, high):
            """
            :param root: 当前根节点,假设当前根节点是存在的
            :param high: 表示当前根节点root的层级
            :return: None
            """
            if root:  # 判断当前根节点是否真的存在
                inner_func(root.left_child, high+1)
                inner_func(root.right_child, high+1)
                nonlocal deepth
                if deepth < high:
                    deepth = high

        inner_func(self.root, 1)
        return deepth

    def get_high_post_2(self):
        """
        获取树的高度,后序遍历方法2
        精髓在于对(root层级+左子树高度)与(root层级+右子树高度)进行对比
        由于后序遍历不需要保留root的层级,也就不需要high参数了
        :return: 树的高度
        """
        def inner_func(root):
            """
            :param root: 当前根节点,当前根节点是否存在并知道,没有做出假设
            :return: 树的高度
            """
            if root:  # 判断当前根节点是否存在
                h_left = inner_func(root.left_child)
                h_right = inner_func(root.right_child)
                return max(h_left, h_right) + 1
            else:
                return 0
        return inner_func(self.root)

    def left_right_swap_pre(self):
        """
        先序递归遍历,交换左右子树
        :return:
        """
        def inner_func(root):
            if root:
                root.left_child, root.right_child = root.right_child, root.left_child
                inner_func(root.left_child)
                inner_func(root.right_child)
        inner_func(self.root)

    def left_right_swap_post(self):
        """
        后序递归遍历,左右子树交互
        注意:
            左右子树的交换不能使用中序遍历。原因:假设对当前根节点来说,以其左孩子为根节点的左子树已交换成功,
            此时在交换当前根结点的左右子树,交换完后。导致左子树还未交换,而右子树已交换。在接下来的会交换右子树,
            交换后导致整棵树还是最初的结构,并未实现左右子树的交换。
        """
        def inner_func(root):
            if root:
                inner_func(root.left_child)
                inner_func(root.right_child)
                root.left_child, root.right_child = root.right_child, root.left_child
        inner_func(self.root)


def like(bi_tree1, bi_tree2):
    """
    判断两棵子树相似性
    算法思想:
        like(bi_tree1, bi_tree2)=True,若t1=t2=None;
        like(bi_tree1, bi_tree2)=False,若t1与t2之一为None,另一个不为None;
        like(bi_tree1, bi_tree2)=like(bi_tree1.left_child, bi_tree2.left_child) and like(bi_tree1.right_child, bi_tree2.right_child),若t1、t2均不为空
    :param bi_tree1: 第一棵子树
    :param bi_tree2: 第二棵子树
    :return: True or False
    """
    if not bi_tree1 and not bi_tree1:
        return True
    elif bi_tree1 and bi_tree2:
        like1 = like(bi_tree1.left_child, bi_tree2.left_child)
        like2 = like(bi_tree1.right_child, bi_tree2.right_child)
        return like1 and like2
    else:
        return False


def path(bi_tree, bi_node):
    """
    获取从二叉树根节点到指定结点之间的路径
    算法思想:
        (1) 由于后序遍历访问到bi_node所指结点时,此时栈种所有结点均为bi_node所指结点的祖先,由这些祖先便
            构成了一条从根节点到bi_node所指结点之间的路径,古应采用后序遍历方法。
        (2) 由于递归方式的战区是由系统隐士控制,为了能在找到结点bi_node时控制输出,需要将递归方式中系统
            隐含的栈变成为用户自己控制的栈,故应使用非递归的后序遍历算法。此算法与后序非递归算法相似。
    :param bi_tree: 二叉树根节点
    :param bi_node: 指定结点
    :return: 路径
    """
    from collections import deque

    path = deque()  #
    temp_root = None
    p = bi_tree
    while p or path:
        if p:
            path.append(p)  # 将当前结点入栈
            p = p.left_child  # 当前结点更新为当前结点的左孩子
        else:
            # print("++++++++++")
            p = path.pop()  # 将栈顶结点出栈,获取当前结点
            path.append(p)  # 由于此时并不是真正的出栈只是为了获取栈顶结点,因此还需再次入栈
            if not p.right_child or p.right_child is temp_root:  # 满足两个条件中任意一个,则访问栈顶结点
                # 访问栈顶结点
                if p.value == bi_node.value:  # 判断当前结点是否是bi_node结点
                    return path  # 返回路径
                else:
                    path.pop()  # 栈顶结点已被访问,此时需要出栈
                    temp_root = p  # 将刚访问过的栈顶结点保存起来,以便下一次用于判断
                    p = None  # 将当前结点设置为空,避免对当前结点的左子树再次入栈
            else:
                p = p.right_child  # 将当前结点设置为当前结点的右孩子,为了将当前结点右子树入栈


def layer_order(bi_tree):
    """
    任务:层次遍历二叉树
    问题分析:
        实现层次遍历,需要设置一个队列Q,暂存某层已访问过的结点,同时也保存了该层结点访问的先后次序。按照对
        该层结点访问的先后次序实现对其下层孩子结点的按次序访问。
    算法思想:
        (1) 创建一个空队列;
        (2) 若二叉树bi_tree为空树,则直接返回;
        (3) 将二叉树的根结点指针bi_tree放入队列Q;
        (4) 若队列非空,则重复如下操作。
            a. 对头元素出队列访问该元素;
            b. 若该结点的左孩子非空,则将该结点的左孩子节点人对;
            c. 若该结点的右孩子非空,则将该结点的右孩子结点指针入队。
    :param bi_tree: 二叉树根
    :return: 层次遍历二叉树的序列
    """
    if not bi_tree:
        return
    from collections import deque
    temp_queue = deque()  # 用于暂存已遍历到的结点,并保存了不同层的层级关系和同层结点的先后关系
    trav_seq = deque()  # 存放访问到的结点
    temp_queue.append(bi_tree)  # 二叉树根节点入队
    while temp_queue:
        p = temp_queue.popleft()  # 对头结点出队
        trav_seq.append(p)  # 保存访问到的结点
        if p.left_child:  # 判断当前结点左孩子是否存在
            temp_queue.append(p.left_child)  # 若存在,将当前结点左孩子入队
        if p.right_child:  # 判断当前结点右孩子是否存在
            temp_queue.append(p.right_child)  # 若存在,将当前结点右孩子入队
    return trav_seq  # 返回层次遍历二叉树的序列
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值