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

  

 

 

 

 

 

posted @ 2019-09-09 15:07  nxf_rabbit75  阅读(456)  评论(0编辑  收藏  举报