二叉树总结(构造、遍历、深度.....)(python)

1.二叉树的构造,广度/深度遍历

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      # 从头开始构造 根结点 从下标0 1 2.....

    def add(self, item):
        node = Node(item)
        if self.root is None:  # 如果是一棵空树,一个几点都没有
            self.root = node
            return
        queue = [self.root]     # 用队列来存放根结点
        while queue:
            cur_node = queue.pop(0)    # 从当前队列的头部读取一个结点,根据该结点是否有左孩子来决定是否在队列尾部添加结点
            if cur_node.lchild is None:   # 如果没有左孩子,先将结点挂上去,但还没有存入到列表中
                cur_node.lchild = node
                return
            else:                      # 如果左孩子存在,将左孩子添加到队列的尾部
                queue.append(cur_node.lchild)

            if cur_node.rchild is None:
                cur_node.rchild = node
                return
            else:
                queue.append(cur_node.rchild)

    def breadth_travel(self):
        """广度遍历"""
        if self.root is None:
            return
        queue = [self.root]
        while queue:
            cur_node = queue.pop(0)
            print(cur_node.elem, end=" ")
            if cur_node.lchild:
                queue.append(cur_node.lchild)
            if cur_node.rchild:
                queue.append(cur_node.rchild)

    """ 深度遍历,分以下三种"""

    def preorder(self, node):
        """先序遍历"""
        if node is None:
            return
        print(node.elem, end=" ")
        self.preorder(node.lchild)
        self.preorder(node.rchild)
        
    def inorder(self, node):
        """中序遍历"""
        if node is None:
            return
        self.inorder(node.lchild)
        print(node.elem, end=" ")
        self.inorder(node.rchild)

    def postorder(self, node):
        """后序遍历"""
        if node is None:
            return
        self.postorder(node.lchild)
        self.postorder(node.rchild)
        print(node.elem, end=" ")


if __name__ == "__main__":
    tree = Tree()
    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.breadth_travel()
    print(" ")
    tree.preorder(tree.root)  # 传入一个根结点,找到一棵树
    print(" ")
    tree.inorder(tree.root)
    print(" ")
    tree.postorder(tree.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 
改进:深度遍历的另一种递归形式

返回的是数组形式

class Solution:
    def preorder(self, root):  
        """先序遍历递归形式"""
        if not root:
            return [] 
        return  [root.val] + self.preorder(root.left) + self.preorder(root.right)
   
    def inorder(self, root):  
        """中序遍历递归形式"""
        if not root:
            return [] 
        return  self.inorder(root.left) + [root.val] + self.inorder(root.right)
   
    def postorder(self, root): 
        """后序遍历递归形式"""
        if not root:
            return [] 
        return  self.postorder(root.left) + self.postorder(root.right) + [root.val]

2. 已知前序和中序,重构二叉树,并打印

先序 根-左-右
中序 左-根-右
后序 左-右-根
先序:[1, 2, 4, 7, 3, 5, 6, 8]
中序:[4, 7, 2, 1, 5, 3, 8, 6]
在这里插入图片描述

class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None
        
class Solution:
    # 返回构造的TreeNode根节点    
    def reConstructBinaryTree(self, pre, tin):
        # write code here
        if len(pre) > 0:
            root = TreeNode(pre[0])
            rootindex = tin.index(root.val)      # 找出pre的第一个根结点在tin中的索引(位置)
            root.left = self.reConstructBinaryTree(pre[1:rootindex+1], tin[:rootindex])
            root.right = self.reConstructBinaryTree(pre[rootindex+1:], tin[rootindex+1:])
            return root
        
    def breadth_travel(self,root):
        newlist = []
        if root is None:
            return newlist
        queue = [root]
        while queue:
            # 队列前部弹出结点,尾部依次追加左右孩子。弹出的结点放入新建的列表中
            cur_node = queue.pop(0)
            newlist.append(cur_node.val)   # 在队列中弹出一个数,往列表中追加一个数

            if cur_node.left:
                queue.append(cur_node.left)    # 队列尾部追加左右孩子,
            if cur_node.right:
                queue.append(cur_node.right)
        return newlist

# 测试部分
pre = [1, 2, 4, 7, 3, 5, 6, 8]
tin = [4, 7, 2, 1, 5, 3, 8, 6]
s = Solution()
root = s.reConstructBinaryTree(pre, tin)   # 根据前中序列,重构二叉树
res = s.breadth_travel(root)   # 将重构的而查树通过广度遍历再次打印。
print(res)        

结果

[1, 2, 3, 4, 5, 6, 7, 8]

3. 二叉树的深度/高度/宽度

1) 深度

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def TreeDepth(self, pRoot):
        # write code here
        if not pRoot:
            return 0
        left = self.TreeDepth(pRoot.left)
        right = self.TreeDepth(pRoot.right)
        return max(left, right) + 1
#        if left >= right:
#           return left + 1
#        else:
#           return right

2) 待更新

4. 树的子结构

方法1:判断B树是否为A树的子结构

class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None
class Solution:
    def IsSubtree(self, pRoot1, pRoot2):
        # write code here
        # 如果2树遍历完都能对应
        if not pRoot2:
            return True
        # 如果pRoot1这棵树遍历完,pRoot2还没遍历完,一定不是
        if not pRoot1:
            return False
        # 如果有节点不等,返回false
        if pRoot1.val != pRoot2.val:
            return False
        # 如果根节点对应的上,那么就分别去子节点里面匹配
        return self.IsSubtree(pRoot1.left, pRoot2.left) and self.IsSubtree(pRoot1.right, pRoot2.right)

    def HasSubtree(self, pRoot1, pRoot2):
        # write code here
        result = False
        if pRoot1 and pRoot2:
            # 以这个根节点为起点判断是否包含
            if pRoot1.val == pRoot2.val:
                result = self.IsSubtree(pRoot1, pRoot2)
            # 如果第一个节点没有匹配上,往下找子节点能否匹配上
            if not result:
                result = self.HasSubtree(pRoot1.left, pRoot2)
            #  如果左子树中匹配不上,就去右子树匹配
            if not result:
                result = self.HasSubtree(pRoot1.right, pRoot2)
        return result
        
# 测试代码
pRoot1 = TreeNode(8)
pRoot1.left = TreeNode(8)
pRoot1.right = TreeNode(7)
pRoot1.left.left = TreeNode(9)
pRoot1.left.right = TreeNode(2)
pRoot1.right.left = TreeNode(4)
pRoot1.right.right = TreeNode(7)

pRoot2 = TreeNode(8)
pRoot2.left = TreeNode(9)
pRoot2.right = TreeNode(2)
s = Solution()
res = s.HasSubtree(pRoot1, pRoot2)
print(res)

方法2:将结点转换成字符串存储,再判断串2是否在串1内

class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None
class Solution:
    def HasSubtree(self, pRoot1, pRoot2):
        # write code here
        if not pRoot1 or not pRoot2:
            return False
        # 将两棵树进行先序排列,并转换成字符串
        str1 = self.preorder(pRoot1)    # '124##5##36##7##'
        str2 = self.preorder(pRoot2)    # '24##5##'
        if str2 in str1:
            return True
        else:
            return False

    def preorder(self, root):
        res = ''         # 构造空字符串
        if not root:     # 结点一直往下分割,直至该结点下无子结点,就必须有返回值,用#填补
            return '#'
        res += str(root.val)   # 将每一个结点转换成字符串
        res += self.preorder(root.left)
        res += self.preorder(root.right)
        return res

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值