zoukankan      html  css  js  c++  java
  • 6.1 数据结构---树(遍历)

    一、树的定义

    1.定义

    是n(n>=0)个节点的有限集,且这些节点满足如下关系:

    (1)有且仅有一个节点没有父节点,该节点称为树的根;

    (2)除根外,其余的每个节点都有且仅有一个父节点;

    (3)树中的每一个节点都构成一个以它为根的树。

    二叉树在满足树的条件时,满足如下条件:每个节点最多有两个孩子(子树),这两个子树有左右之分,次序不可颠倒。

    2.树的遍历

    二、先序遍历

    1.先序遍历

    递归

    class TreeNode:
        def __init__(self, x):
            self.val = x
            self.left = None
            self.right = None
    
    class Solution:
        def preorderTraversal(self,root):
            '''
            递归,时间复杂度O(n),空间复杂度平均O(logn),最坏情况下O(n)
            :param root:
            :return:
            '''
            if root:
                print(root.val)
            else:
                return
            self.preorderTraversal(root.left)
            self.preorderTraversal(root.right)

    非递归:时间复杂度O(n),空间复杂度O(n)

    思路:

    1)申请一个新的栈,把头结点压入栈中
    2)从栈中弹出栈顶节点,记为node,然后打印node节点的值,再将节点node的由孩子先压入stack中,最后将node的左孩子压入stack中
    3)不断重复步骤2,直到栈为空,过程结束

    class TreeNode:
        def __init__(self, x):
            self.val = x
            self.left = None
            self.right = None
    
    class Solution:
        def preorderTraversal1(self,root):
            '''
            :param root:
            :return:
            '''
            if root == None:
                return
    
            res = []
            stack = [root]
            while stack:
                node = stack.pop()
                print(node.val)
                res.append(node.val)
                if node.right:
                    stack.append(node.right)
                if node.left:
                    stack.append(node.left)
            return res

    2.左叶子之和

    leetcode 404

    3.判断一棵树是不是平衡树

    4.复制二叉树

    5.求二叉树的所有叶子节点,并且判断两棵二叉树的叶子节点是否相等

    思路1:用先序遍历按左到右顺序遍历所有叶子节点,并返回,然后判断两棵树的叶子序列是否相等。

    时间复杂度O(T1+T2)  空间复杂度O(T1+T2)

    # Definition for a binary tree node.
    # class TreeNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.left = None
    #         self.right = None
     
    class Solution:
        def leafSimilar(self, root1: TreeNode, root2: TreeNode) -> bool:
            values1,values2=[],[]
            self.printleaf(root1,values1)
            self.printleaf(root2,values2)
            if values1 == values2:
                return True
            else:
                return False
         
        def printleaf(self,root,values):
            if root == None:
                return
            if root.left == None and root.right == None:
                values.append(root.val)
            self.printleaf(root.left,values)
            self.printleaf(root.right,values)

    思路2:dfs

    class Solution:
        def leafSimilar(self, root1, root2):
            def dfs(node):
                if node:
                    if not node.left and not node.right:
                        yield node.val
                    yield from dfs(node.left)
                    yield from dfs(node.right)
     
            return list(dfs(root1)) == list(dfs(root2))
    

      

    三、中序遍历

    1.中序遍历

    递归:时间复杂度O(n),空间复杂度平均O(logn),最坏情况下O(n)

    class TreeNode:
        def __init__(self, x):
            self.val = x
            self.left = None
            self.right = None
    
    class Solution:
        def inorderTraversal(self,root):
            '''
            :param root:
            :return:
            '''
            if root == None:
                return
            self.inorderTraversal(root.left)
            print(root.val)
            self.inorderTraversal(root.right)

    非递归:时间复杂度O(n),空间复杂度O(n)

    思路:

    1)申请一个新的栈,初始时,令变量node=head
    2)先把node节点压入栈中,对以node节点为头的整棵子树来说,依次把左边界压入栈中,即不停的令node=node.left,然后重复步骤2
    3)不断重复步骤2,直到发现node为空,此时,从栈中弹出一个节点,记为node,打印node的值,并且让node=node.right,然后继续重复步骤2
    4)当stack为空且cur为空时,整个过程停止.

    class Solution:
        def inorderTraversal1(self,root):
            '''
            :param root:
            :return:
            '''
            if root == None:
                return
            res = []
            stack = []
            node = root
            while stack or node:
                if node:
                    stack.append(node)
                    node = node.left
                else:
                    node = stack.pop()
                    res.append(node.val)
                    node = node.right
            return res

    2.判断一棵树是不是二叉搜索树

    3.在二叉排序树中找出第一个大于中间值的借贷

    4.二叉树转换为双向链表

    四、后序遍历

    1.后序遍历

    递归:时间复杂度O(n),空间复杂度平均O(logn),最坏情况下O(n)

    class TreeNode:
        def __init__(self, x):
            self.val = x
            self.left = None
            self.right = None
    
    class Solution:
        def posorderTraversal(self,root):
            '''
            :param root:
            :return:
            '''
            if root == None:
                return
            self.posorderTraversal(root.left)
            self.posorderTraversal(root.right)
            print(root.val)
    

    非递归

    a.两个栈:时间复杂度O(n),空间复杂度O(n)

    思路:用两个栈实现后序遍历
    1)申请一个栈,记为s1,然后将头结点head压入栈Ss1中;
    2)从s1中弹出的节点记为cur,然后依次将cur的左孩子和右孩子压入s1中;
    3)从整个过程中,每一个从s1中弹出的节点都放进s2中;
    4)不断重复步骤2和步骤3,直到s1为空,过程停止;
    5)从s2中依次弹出节点并打印,打印的顺序就是后序遍历的顺序.

    class Solution:
        def posorderTraversal1(self,root):
            '''
            :param root:
            :return:
            '''
            if not root:
                return []
            s1,s2 = [root],[]
            while s1:
                cur = s1.pop()
                s2.append(cur.val)
                if cur.left:
                    s1.append(cur.left)
                if cur.right:
                    s1.append(cur.right)
            return s2[::-1]

    b.一个栈

    思路:用一个栈实现后序遍历
    申请一个栈,将头结点压入栈中,同时设置变量h和c,h代表最近一次弹出并打印的节点,c代表stack的栈顶节点,初始时h为头结点,c为null

    def posorderTraversal2(self,root):
        '''
        :param root:
        :return:
        '''
        if not root:
            return []
        res = []
        cur = [root]
        while cur:
            node = cur[-1]
            if node.left and node.left != root and node.right != root:
                cur.append(node.left)
            elif node.right and node.right != root:
                cur.append(node.right)
            else:
                res.append(cur.pop().val)
                root = node
        return res

    2.二叉树的最小深度

    leetcode 111

    3.判断一个数组是否是二元查找树后序遍历的序列

    4.对二叉树进行镜像反转

    5.求二叉树的最大子树和

    五、层次遍历

    1.层次遍历

    递归

    思路:每次遍历到新层,层数+1,

    class Solution:
        def levelOrder(self,root,level,result):
            '''
            递归,按层输出
            :param root:
            :param level:
            :param result:
            :return:
            '''
            if root == None:
                return
            if level == len(result): # 如果遍历到了新层,就新建一个[]用来存放新层的值
                result.append([])
            result[level].append(root.val)
            if root.left:
                self.levelOrder(root.left,level+1,result)
            if root.right:
                self.levelOrder(root.right,level+1,result)
    
        def levelOrder1(self, root):
            """
            :type root: TreeNode
            :rtype: List[List[int]]
            """
            level,result = 0,[]
            self.levelOrder(root,level,result)
            return result

    非递归

    思路:用一个队列记录

    def levelOrder2(self,root):
        '''
        思路:队列
        用队列存储节点,每次左边出一个节点,如果该节点有左右节点,就将左右节点入队列,直到队列空为止
        :param root:
        :return:
        '''
        from collections import deque
        if root == None:
            return
        queue = deque()
        queue.append(root)
        res = []
        while queue:
            node = queue.popleft()
            res.append(node.val)
            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)
    

    2.二叉树的锯齿形层次遍历 leetcode103

    3.二叉树自底向上层次遍历

    4.判断一棵树是不是二叉完全树

    5.找树左下角的值 leetcode153

    思想:层次遍历找最后一层的第一个节点的值

    # Definition for a binary tree node.
    # class TreeNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.left = None
    #         self.right = None
     
    class Solution:
        def findBottomLeftValue(self, root: TreeNode) -> int:
            #层次遍历,找最后一层的第一个数
            self.res = []
            def levelOrder(root,level):
                if not root:
                    return
                if len(self.res) == level:#如果层数和res里面的长度相等,说明该层已经遍历完,或者是第一次遍历,就新建一个[],用来放下一层的数据
                    self.res.append([])
                self.res[-1].append(root.val)
                if root.left:
                    levelOrder(root.left,level+1)
                if root.right: 
                    levelOrder(root.right,level+1)
                 
            if not root:
                return
            if not root.left and not root.right:
                return root.val
            levelOrder(root,0)
            return self.res[-1][0]
    

      

    六、给定二叉树前、中序遍历,构造二叉树

    分析:

      前序遍历序列第一个是根节点x

      从中序遍历序列中找到根节点x

      中序遍历中x的左边序列对应等长的前序遍历序列【左子树】

      中序遍历中的x的右边序列对应等长的前序遍历序列【右子树】

    class TreeNode(object):
        def __init__(self, x):
            self.val = x
            self.left = None
            self.right = None
    
    def buildTree(preorder,inorder):
        if preorder == []:
            return None
        val = preorder[0]
        idx = inorder.index(val)
        l_inorder = inorder[0:idx]
        r_inorder = inorder[idx+1:]
        l_preorder = preorder[1:1+len(l_inorder)]
        r_preorder = preorder[1+len(l_inorder):]
        root = TreeNode(val)
        root.left = buildTree(l_preorder,l_inorder)
        root.right = buildTree(r_preorder,r_inorder)
        return root
    

     

    七、给定二叉树中、后序遍历,构造二叉树

    class TreeNode(object):
        def __init__(self, x):
            self.val = x
            self.left = None
            self.right = None
    
    def buildTree(inorder,postorder):
        if postorder == []:
            return None
        val = postorder[-1]
        idx = inorder.index(val)
        l_inorder = inorder[0:idx]
        r_inorder = inorder[idx+1:]
        l_postorder = postorder[:len(l_inorder)]
        r_postorder = postorder[len(l_inorder):-1]
        root = TreeNode(val)
        root.left = buildTree(l_inorder,l_postorder)
        root.right = buildTree(r_inorder,r_postorder)
        return root
    

      

     

  • 相关阅读:
    Windows Server 2008 R2 免费使用 7200天 激活
    ceph部署步骤
    for循环间隔修改(解决把以空格隔开需要把一整行作为整体)
    my_learn
    fiddler-抓包
    基础软件搭建
    【原创】一层Nginx反向代理K8S化部署实践
    【原创】K8S使用ceph-csi持久化存储之CephFS
    【原创】K8S使用ceph-csi持久化存储之RBD
    [原创]自动化部署K8S(v1.10.11)集群
  • 原文地址:https://www.cnblogs.com/nxf-rabbit75/p/11491809.html
Copyright © 2011-2022 走看看