PTA-树的遍历(python实现)

自己做题过程中的一些想法,做一个记录,方便以后查看,如果能给读者一些启发也是极好的。欢迎大家的批评指正和交流讨论。

题目描述:

给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列。这里假设键值都是互不相等的正整数。

输入格式:

输入第一行给出一个正整数N(≤30),是二叉树中结点的个数。第二行给出其后序遍历序列。第三行给出其中序遍历序列。数字间以空格分隔。

输出格式:

在一行中输出该树的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。

输入样例:

7
2 3 1 5 7 6 4
1 2 3 4 5 6 7

输出样例:

4 1 6 3 5 7 2

思路:

题目给出了后序遍历和中序遍历,需要输出层序遍历,首先要做的就是根据后序遍历和中序遍历的结果重构这棵二叉树,然后再做层序遍历,层序遍历借助队列来实现(先进先出)。

具体过程:

第一步:建构二叉树

后序遍历即是“左-右-根”的顺序遍历二叉树,由此我们可以知道后序遍历的最后一个值就是二叉树的根节点的值;中序遍历即是“左-根-右”的顺序遍历二叉树,因此根据后序遍历找到根节点后,就可以根据该根节点的值(这里假设二叉树的每个结点值都不相同)在中序遍历找到相应的位置,从该位置以左就是二叉树的左子树,以右就是二叉树的右子树。根据左子树和右子树结点的个数可以在后序遍历的序列中找到相应的左子树和右子树对应的序列。同理,后序遍历的左子树序列最后一个值就是左子树的根节点,右子树序列的最后一个值就是右子树的根节点。

图示:

这个不断寻找每个结点的左子树和右子树的过程可以通过递归来实现,我们可以每次找到一个子树的根节点后就将它的值从后序遍历的序列中删除,子树的结构通过中序遍历的顺序来判断。直到每个结点都没有左子树且没有右子树,递归返回的条件就可以据此设置为后序遍历的序列是否为空。

第二步:层序遍历输出

借助“队列”先进先出的结构来对二叉树进行层序遍历,首先把根节点放入空队中,然后弹出队列中第一个值,并把它的左节点和右节点放入队列的队尾。之后循环判断队列是否为空,不空则每次弹出队首的元素,并且把弹出元素的左节点和右节点放入队尾,直到最后队列为空退出循环。这个更详细的解释可以去看MOOC上浙江大学的课程《数据结构》,老师讲的很易懂。

代码:

有些注释是为了检查程序是否有问题

#7-10 树的遍历
n=int(input())
back=list(map(int,input().split()))
middle=list(map(int,input().split()))

'''定义队列'''
class Queue():
    def __init__(self):
        #创建一个空队列
        self.item=[]
    def isEmpty(self):
        #判断是否空队列
        return len(self.item)==0
    def enQueue(self,elemt):
        #向队尾加入元素。定义0为队尾,n为队首
        self.item.insert(0,elemt)
    def deQueue(self):
        #抛出队首元素
        if self.isEmpty():
            raise Exception('Queue is empty.')
        return self.item.pop()
    def len(self):
        #返回队列中元素个数
        return len(self.item)
    def first(self):
        #返回队列第一个元素但不移除
        #队列为空则触发一个错误
        if self.isEmpty():
            raise Exception('Queue is empty.')
        return self.item[-1]
    def queueList(self):
        #返回队列所有元素
        if self.isEmpty():
            raise Exception('Queue is empty.')
        else:
            return self.item[::-1]

'''定义二叉树结点'''
class TreeNode():
    def __init__(self,val,Left=None,Right=None):
        '''val--结点值,Left--左结点,Right--右结点'''
        self.val=val
        self.Left=Left
        self.Right=Right
    def printNode(self):
        #打印结点值
        print(self.val)

'''根据后序遍历和中序遍历建立树'''
def create_tree(backorder,midorder):
    if not backorder:
        return None
    else:
        root_val=backorder.pop()
        root=TreeNode(root_val)
        root_idx=midorder.index(root_val)
        ll=len(midorder[:root_idx])     #左子树长度
        rl=len(midorder[root_idx+1:])   #右子树长度
        # print("ll:",ll,"rl:",rl)

        root.Left=create_tree(backorder[:ll],midorder[:root_idx])
        root.Right=create_tree(backorder[ll:ll+rl],midorder[root_idx+1:])
        # print(type(root))
        return root

'''定义层序遍历'''
def level_order_travsal(root):
    if not root:
        return None
    else:
        result=[]
        Que=Queue()
        # print('level order:',type(root))
        Que.enQueue(root)
        while(not Que.isEmpty()):
            rt=Que.deQueue()
            # print('loop:',type(rt))
            result.append(rt.val)
            if rt.Left:
                Que.enQueue(rt.Left)
            if rt.Right:
                Que.enQueue(rt.Right)
        return result

# back=[2,3,1,5,7,6,4]
# middle=[1,2,3,4,5,6,7]
root=create_tree(back,middle)
result=level_order_travsal(root)
for i in range(n-1):
    print(result[i],end=' ')
print(result[n-1])
  • 10
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值