Python实现完全二叉树以及遍历

早过忘川 提交于 2020-03-11 17:57:09
  • 在学校刚刚学到的二叉树是用C语言来实现的,还涉及到了指针等操作。最近疫情原因不能开学,就自己学习了一下Python,就拿Python来试着实现一下,顺便再复习一下二叉树的一些知识。

  • 本文使用Python来构建一个完全二叉树,并且实现树结点添加,层次遍历,先序遍历,中序遍历,后序遍历。

  • 由于我自己对二叉树的理解也不是很深,所以关于二叉树的理论知识就只能自行脑补了,这里直接开始实现了,在实现的过程中也可能会有一些错误,还请大佬们批评指正。

  • 以下为实现的思路,完整代码以及输出可以直接滑倒最后查看。

  • 创建结点

  • 首先创建一个结点的类,结点含有数据和左子,右子,创建后就直接将左子,右子初始化为None,数据则从外部输入进去。

# 创建一个结点的class
class Node(object):
    def __init__(self,valua):
        self.valua = valua
        self.Lchild = None
        self.Rchild = None
  • 然后创建一个二叉树的类,因为结点已经创建了一个node的类,这里只需要初始化一个根结点为None就可以了。
# 创建一个二叉树class
class Btree(object):
    def __init__(self):
        # 初始化根结点
        self.root = None
  • 添加结点

  • 接下来就可以来实现添加结点的funtion类。

  • 实现思路主要是使用层次遍历来查找空的位置,先检查根节点是否为空,如果为空就直接把添加的结点赋值给根节点。

  • 如果结点的左子为空就将结点添加到左子的位置,然后再检查右子。

  • 这里使用了队列来进行查找,首先把根节点放在队列中。然后弹出第一个元素来判断左子右子是否为空,如果为空就直接赋值返回,如果不为空就把当前的结点添加到队列末尾,一直查找下去其实也相当于对树进行了层次的遍历,找到符合的位置后把该结点添加进去然即可。

def add_node(self,valua):
        node = Node(valua)
        # 如果根结点为空,则赋值给根结点
        if self.root is None:
            self.root = node
            return
        # 初始化队列,用于遍历
        queue = [self.root]
        while queue:
            # 弹出第一个结点,先判断左子,后判断右子
            # 如果为空,则赋值,否加入队列,为了下一次遍历使用
            pop_node = queue.pop(0)
            if pop_node.Lchild is None:
                # print("add in Lchild",node.valua)
                pop_node.Lchild = node
                return
            else:
                queue.append(pop_node.Lchild)
            if pop_node.Rchild is None:
                pop_node.Rchild = node
                return
            else:
                queue.append(pop_node.Rchild)
  • 这里比较难理解的可能是队列的使用,这里使用了pop操作,取出后就把队列的第一个元素给删除了。已经删除的就说明已经查找过来,如果队列还有元素就说明还没有查找到最后一个,完全二叉树也就还没有遍历结束。
  • 添加到队列中的元素实际上也是按照层次遍历的顺序进行添加到,这样查找就能从根节点按照层次一直查找到最后一个结点,最终完成添加过程。
  • 层次遍历
  • 接下来是对二叉树的层次遍历,层次遍历和增加结点类似,也是使用队列来进行,如果左子或者右子不为空就继续输出下去就行了 。
# 层次遍历
    def level_order(self):
        # 使用队列进行,拿出第一个元素输出
        # 先判断左子,后判断右子,如果不为空则加到队列中,继续遍历

        # 判断根节点,如果为空则为空树
        if self.root is None:
            return
        print(self.root.valua,end=' ')
        queue = [self.root]
        while queue:
            node = queue.pop(0)
            if node.Lchild is not None:
                print(node.Lchild.valua,end=' ')
                queue.append(node.Lchild)
            if node.Rchild is not None:
                print(node.Rchild.valua,end=' ')
                queue.append(node.Rchild)

  • 先序遍历
  • 先序遍历的顺序为:根 左 右
  • 这里使用递归来实现,先输出根节点的值,然后递归查找左子,再递归查找右子。
  • 递归的终止条件为当前遍历的结点为空。
def pre_order(self,node):
        # 先序遍历 先打印根节点的数据,递归下去
        # 结点为空时结束递归
        if node is None:
            return
        print(node.valua,end=' ')
        self.pre_order(node.Lchild)
        self.pre_order(node.Rchild)
  • 中序遍历
  • 中序遍历的顺序为:左 根 右
  • 中序遍历与先序遍历的思路一样,只是先输出左子的值,在代码实现上仅仅是把输出函数改了下位置而已。
    def in_order(self,node):
        # 中序遍历  
        if node is None:
            return
        self.in_order(node.Lchild)
        print(node.valua,end=' ')
  • 后序遍历
  • 后序遍历的顺序为:左 右 根
  • 实现思路和前面的先序和中序相同,改变了一下先输出的值。
    def post_order(self,node):
        # 后序遍历
        if node is None:
            return
        self.post_order(node.Lchild)
        self.post_order(node.Rchild)
        print(node.valua,end=' ')

完整代码

# 创建一个结点的class
class Node(object):
    def __init__(self,valua):
        self.valua = valua
        self.Lchild = None
        self.Rchild = None

# 创建一个二叉树class
class Btree(object):
    def __init__(self):
        # 初始化根结点
        self.root = None
    # 增加结点(广度搜索)
    def add_node(self,valua):
        node = Node(valua)
        # 如果根结点为空,则赋值给根结点
        if self.root is None:
            self.root = node
            return
        # 初始化队列,用于遍历
        queue = [self.root]
        while queue:
            # 弹出第一个结点,先判断左子,后判断右子
            # 如果为空,则赋值,否加入队列,为了下一次遍历使用
            pop_node = queue.pop(0)
            if pop_node.Lchild is None:
                # print("add in Lchild",node.valua)
                pop_node.Lchild = node
                return
            else:
                queue.append(pop_node.Lchild)
            if pop_node.Rchild is None:
                pop_node.Rchild = node
                return
            else:
                queue.append(pop_node.Rchild)
    # 层次遍历
    def level_order(self):
        # 使用队列进行,拿出第一个元素遍历
        # 先判断左子,后判断右子,如果不为空则加到队列中,继续遍历

        # 判断根节点,如果为空则为空树
        if self.root is None:
            return
        print(self.root.valua,end=' ')
        queue = [self.root]
        while queue:
            node = queue.pop(0)
            if node.Lchild is not None:
                print(node.Lchild.valua,end=' ')
                queue.append(node.Lchild)
            if node.Rchild is not None:
                print(node.Rchild.valua,end=' ')
                queue.append(node.Rchild)

    def pre_order(self,node):
        # 先序遍历 先打印根节点的数据,递归下去
        # 结点为空时结束递归
        if node is None:
            return
        print(node.valua,end=' ')
        self.pre_order(node.Lchild)
        self.pre_order(node.Rchild)
    def in_order(self,node):
        # 中序遍历  
        if node is None:
            return
        self.in_order(node.Lchild)
        print(node.valua,end=' ')
        self.in_order(node.Rchild)
    def post_order(self,node):
        # 后序遍历
        if node is None:
            return
        self.post_order(node.Lchild)
        self.post_order(node.Rchild)
        print(node.valua,end=' ')
#创建一个二叉树
a = Btree()
a.add_node(0)
a.add_node(1)
a.add_node(2)
a.add_node(3)
a.add_node(4)
a.add_node(5)
a.add_node(6)
a.add_node(7)
a.add_node(8)
a.add_node(9)

print('层次遍历:',end=' ')
a.level_order()
print('\n先序遍历:',end=' ')
a.pre_order(a.root)
print('\n中序遍历:',end=' ')
a.in_order(a.root)
print('\n后序遍历:',end=' ')
a.post_order(a.root)
  • 输出结果
层次遍历: 0 1 2 3 4 5 6 7 8 9 
先序遍历: 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 
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!