• 数据结构和算法-二叉树


    二叉树的两颗子树有明确的左右之分.
    说子树时必须说明是左子树/右子树. 根节点从1开始计数. 高度和深度是从0开始, 层数是从1开始

    • 在非空二叉树第i层中至多有2**(i-1)次方个结点
    • 在高度为h的二叉树总结点数最多为2**(h+1)-1个结点
    • 序号为1的点是根
    • 对于i>0, 其父节点的编号是i/2
    • 如果节点i有左右子节点, 那么左子树编号是2*i, 右节点编号是2*i+1

    种类

    • 满二叉树
      除了叶子节点外其它节点都有左右子节点
    • 完全二叉树
      叶子节点在最底下两层, 最后一层的叶子节点都靠左排列. 除了最后一层其它层的节点个数达到最大

    存储方式

    • 链式存储法(链表)
    • 顺序存储法(数组)
      如果一棵树是完全二叉树, 那么使用数组存储是最节省空间的方式

    遍历

    遍历即将树的所有结点访问一次, 按照节点位置的不同分为前序遍历, 中序遍历, 后序遍历

    • 前序遍历: 根节点-->左子树-->右子树 (DBACEGF)
    • 中序遍历: 左子树-->根节点-->右子树 (ABCDEFG)
    • 后序遍历: 左子树-->右子树-->根节点 (ACBFGED)
    # coding:utf-8
    
    
    """
    二叉树遍历
    时间复杂度: O(n)
    """
    
    
    class BinaryTree(object):
        def __init__(self, data, left=None, right=None):
            self.data = data
            self.left = left
            self.right = right
    
    
    def pre(root):
        """前序遍历"""
        if root is None:
            return
        print(root.data, end="")
        pre(root.left)
        pre(root.right)
    
    
    def mid(root):
        """中序遍历"""
        if root is None:
            return
        pre(root.left)
        print(root.data, end="")
        pre(root.right)
    
    
    def after(root):
        """后续遍历"""
        if root is None:
            return
        pre(root.left)
        pre(root.right)
        print(root.data, end="")
    
    
    def level(root):
        """
        按层级遍历, 广度优先遍历
        :param root:
        :return:
        """
        from collections import deque
    
        d = deque([])
        d.append(root)
        while d:
            node = d.popleft()
            print(node.data, end="")
            if node.left:
                d.append(node.left)
            if node.right:
                d.append(node.right)
    
    
    if __name__ == '__main__':
        root = BinaryTree(
            'D',
            BinaryTree(
                'B',
                BinaryTree('A'),
                BinaryTree('C')
            ),
            BinaryTree(
                'E',
                right=BinaryTree(
                    'G',
                    BinaryTree('F')
                )
            )
        )
        pre(root)
        print("
    ")
        mid(root)
        print("
    ")
        after(root)
        print("
    ")
        level(root)
    
    """
    DBACEGF
    
    BACDEGF
    
    BACEGFD
    
    DBEACGF
    """
    
    

    广度优先

    使用队列

    # coding:utf-8
    
    from collections import deque
    
    class Node(object):
        def __init__(self, value, left=None, right=None):
            self.value = value
            self.left = left
            self.right = right
    
    
    def width(root):
        if root is None:
            return
        queue = []
        d = deque(queue)
        d.append(root)
    
        while d:
            node = d.popleft()
            print(node.value),
            if node.left:
                d.append(node.left)
            if node.right:
                d.append(node.right)
    
    
    if __name__ == '__main__':
        root = Node('D',Node('B',Node('A'),Node('C')),Node('E',right=Node('G',Node('F'))))
        width(root)
    
    
    
    
    """
    D B E A C G F
    """
    
    

    深度优先遍历

    使用栈

    # coding:utf-8
    
    """
    深度优先遍历
    """
    
    from collections import deque
    
    
    class Node(object):
        def __init__(self, data, left=None, right=None):
            self.data = data
            self.left = left
            self.right = right
    
    
    def depth(root):
        if root is None:
            return
        res = []
    
        d = deque([])
        d.append(root)
        while d:
            node = d.pop()
            res.append(node.data)
            if node.right:
                d.append(node.right)
            if node.left:
                d.append(node.left)
    
        return res
    
    
    if __name__ == '__main__':
        root = Node('D', Node('B', Node('A'), Node('C')), Node('E', right=Node('G', Node('F'))))
        res = depth(root)
        assert res == ["D", "B", "A", "C", "E", "G", "F"]
    
    

    根据前序遍历和中序遍历, 求后续遍历

    分析: 前序遍历的第一个值就是根节点, 然后在中序遍历中找到这个值, 那么这个值的左边部分就是当前二叉树的左子树部分中序遍历结果, 这个值的右边部分就是当前二叉树的右子树部分中序遍历结果. 因此, 通过这个分析, 可以恢复这颗二叉树

    #!/usr/bin/env python
    # coding:utf-8
    
    pre = list('DBACEGF')
    mid = list('ABCDEFG')
    after = []
    
    def find_after_tree(pre, mid, after):
        if len(pre) == 0:
            return
        if len(pre) == 1:
            after.append(pre[0])
            return
        # 根据前序遍历得到根节点
        root = pre[0]
        # 在中序遍历中得到根节点的位置, 那么左半部分就是左子树, 另外是右子树
        n = mid.index(root)
        find_after_tree(pre[1:n+1], mid[:n], after)
        find_after_tree(pre[n+1:], mid[n+1:], after)
        # 最后把根节点添加进去
        after.append(root)
    
    find_after_tree(pre, mid, after)
    print after
    
    
    """
    ['A', 'C', 'B', 'F', 'G', 'E', 'D']
    """
    
    

    求最大树深

    # coding:utf-8
    
    """
    求最大树深
    """
    
    def get_max_depth(root):
        if root is None:
            return -1
        return max(get_max_depth(root.left), get_max_depth(root.right)) + 1
    

    求两个树是否相同

    # coding:utf-8
    
    """
    求两个树是否完全相同
    """
    
    
    def is_same_tree(tree1, tree2):
        if tree1 is None and tree2 is None:
            return True
        elif tree1 and tree2:
            return tree1.data == tree2.data and is_same_tree(tree1.left, tree2.left) and is_same_tree(tree1.right,
                                                                                                      tree2.right)
        else:
            return False
    
    
  • 相关阅读:
    BZOJ1293: [SCOI2009]生日礼物
    BZOJ2326: [HNOI2011]数学作业
    BZOJ1179: [Apio2009]Atm
    树链剖分的一个小细节
    BZOJ1146: [CTSC2008]网络管理Network
    BZOJ1984: 月下“毛景树”
    BZOJ3196: Tyvj 1730 二逼平衡树
    BZOJ1579: [Usaco2009 Feb]Revamping Trails 道路升级
    BZOJ1674: [Usaco2005]Part Acquisition
    Babel 在浏览器环境使用方法
  • 原文地址:https://www.cnblogs.com/zlone/p/11012109.html
Copyright © 2020-2023  润新知