剑指offer--树类python

二叉树的遍历是在面试使比较常见的项目了。对于二叉树的前中后层序遍历,每种遍历都可以递归和循环两种实现方法,且每种遍历的递归实现都比循环实现要简洁。下面做一个小结。

1.二叉树的概念

二叉树是每个结点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。
在这里插入图片描述
2.二叉树的前序、中序、后序三种遍历方式

前序遍历:根节点 --> 左子树 -->右子树
中序遍历:左子树 -->根节点 -->右子树
后序遍历: 左子树 -->右子树 -->根节点
层次遍历: 一层一层

3,算法实现
每种遍历都可以递归和循环两种实现方法,且每种遍历的递归实现都比循环实现要简洁。

首先构建树

class TreeNode:
     def __init__(self, x):
         self.val = x
         self.left = None
         self.right = None
 
a = TreeNode(1)
b = TreeNode(2)
c = TreeNode(3)
d = TreeNode(4)
e = TreeNode(5)

 
a.left = b
a.right = c
b.left = d
b.right = e

在这里插入图片描述
递归方法:
中序遍历
递归方法:每次递归,只需要判断结点是不是None,否则按照左中右的顺序打印出结点value值。

中序遍历
class Solution:
    def inorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        if not root:
            return [] 
        return self.inorderTraversal(root.left) + [root.val] + self.inorderTraversal(root.right)

前序遍历
按照上面的说法,前序遍历指根结点在最前面输出,所以前序遍历的顺序是:中左右

class Solution:
    def preorderTraversal(self, root):  ##前序遍历
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        if not root:
            return [] 
        return  [root.val] + self.inorderTraversal(root.left) + self.inorderTraversal(root.right)

后序遍历
后序遍历指根结点在最后面输出,所以后序遍历的顺序是:左右中

def postorderTraversal(self, root):  ##后序遍历
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        if not root:
            return [] 
        return  self.inorderTraversal(root.left) + self.inorderTraversal(root.right) + [root.val]

改动的地方只有return时函数的打印顺序。

非递归方法:主要是使用循环方法
循环比递归要复杂得多,因为你得在一个函数中遍历到所有结点。但是有句话很重要:
对于树的遍历,循环操作基本上要用到栈(stack)这个结构
对于中序遍历的循环实现,每次将当前结点(curr)的左子结点push到栈中,直到当前结点(curr)为None。这时,pop出栈顶的第一个元素,设其为当前结点,并输出该结点的value值,且开始遍历该结点的右子树。
在这里插入图片描述
例如,对于上图的一个二叉树,其循环遍历过程如下表:

在这里插入图片描述
可见-规律为当前结点curr不为None时,每一次循环将当前结点curr入栈,当前结点curr为None时,则出栈一个结点,且打印出栈结点的value值,整个循环在stack和curr皆为None的时候终止。

class Solution:
    def inorderTraversal(self, root): #中序
        stack = []
        sol = []
        curr = root
        while stack or curr:
            if curr:
                stack.append(curr)
                curr = curr.left
            else:
                curr = stack.pop()
                sol.append(curr.val)
                curr = curr.right
        return sol

为什么把前序遍历和后序遍历放在一起呢?Leetcode上前序遍历是medium难度,后序遍历可是hard难度呢!

实际上,后序遍历不就是前序遍历的“反过程”嘛!

先看前序遍历。12453 我们仍然使用栈stack,由于前序遍历的顺序是中左右,所以我们每次先打印当前结点curr,并将右子结点push到栈中,然后将左子结点设为当前结点。入栈和出栈条件(当前结点curr不为None时,每一次循环将当前结点curr入栈;当前结点curr为None时,则出栈一个结点)以及循环结束条件(整个循环在stack和curr皆为None的时候结束)与中序遍历一模一样。

class Solution:
    def preorderTraversal(self, root):  ## 前序遍历
        stack = []
        sol = []
        curr = root
        while stack or curr:
            if curr:
                sol.append(curr.val)
                stack.append(curr.right)
                curr = curr.left
            else:
                curr = stack.pop()
        return sol

再看后序遍历。由于后序遍历的顺序是左右中,我们把它反过来,则遍历顺序变成中左右,是不是跟前序遍历只有左右结点的差异了呢?然而左右的差异仅仅就是.left和.right的差异,在代码上只有机械的差别。

 def postorderTraversal(self, root): ## 后序遍历
        stack = []
        sol = []
        curr = root
        while stack or curr:
            if curr:
                sol.append(curr.val)
                stack.append(curr.left)
                curr = curr.right
            else:
                curr = stack.pop()
        return sol[::-1]

码的主体部分基本就是.right和.left交换了顺序,且后序遍历在最后输出的时候进行了反向(因为要从中右左变为左右中)

层次遍历
层序遍历也可以叫做宽度优先遍历:先访问树的第一层结点,再访问树的第二层结点…然后一直访问到最下面一层结点。在同一层结点中,以从左到右的顺序依次访问。

循环
这里的循环实现不能用栈了,得用队列queue。因为每一层都需要从左往右打印,而每打印一个结点都会在队列中依次添加其左右两个子结点,每一层的顺序都是一样的,故必须采用先进先出的数据结构。
递归实现
递归函数需要有一个参数level,该参数表示当前结点的层数。遍历的结果返回到一个二维列表sol=[[]]中,sol中的每一个子列表保存了对应index层的从左到右的所有结点value值。

https://www.cnblogs.com/bjwu/p/9284534.html

循环实现
  def PrintFromTopToBottom(self, root):
        if root is None:
            return []
        queue=[]
        result=[]
        queue.append(root)
        while len(queue)>0:
            root=queue.pop(0)
            result.append(root.val)
            if root.left is not None:
                queue.append(root.left)
            if root.right is not None:
                queue.append(root.right)
        return result

其实,如果需要打印成zigzag形式(相邻层打印顺序相反),则可以采用栈stack数据结构,正好符合先进后出的形式。sol[level-1].append(node.val)进行一个层数奇偶的判断,一个用append(),一个用insert(0,)

 # 求二叉树节点个数
2 def treeNodenums(node):
3     if node is None:
4         return 0
5     nums = treeNodenums(node.left)
6     nums += treeNodenums(node.right)
7     return nums + 1
1 # 二叉树的最大深度
2 def bTreeDepth(node):
3     if node is None:
4         return 0
5     ldepth = bTreeDepth(node.left)
6     rdepth = bTreeDepth(node.right)
7     return (max(ldepth, rdepth) + 1)

题目1:重建二叉树

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
思路:根节点是前序第一个, 找到根节点在中序序列的位置索引,然后得到左子树和右子树的索引位置,递归调用。

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    # 返回构造的TreeNode根节点
    def reConstructBinaryTree(self, pre, tin):  
        if len(pre)==0 or len(tin)==0:
            return None
        root_data=TreeNode(pre[0])
        i=tin.index(root_data.val)
        root_data.left=self.reConstructBinaryTree(pre[1:1+i],tin[:i])
        root_data.right=self.reConstructBinaryTree(pre[i+1:],tin[i+1:])
        return root_data

那如果知道一棵树,如何把他的前序和中序打印出来呢??

题目2–树的子结构

输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)

思路: 遍历二叉树A,定位B的根节点在A中的可能位置——> 定位后,验证B是不是A当前位置的子结构。**
本题的思路在于子结构的判断,首先需要判断两棵树的根节点是否相同,若是不同则递归调用其左子树和B树,若仍不同则递归调用其右子树和B树,若都不同则返回false。
1.先在A中找和B的根节点相同的结点

2.找到之后遍历对应位置的其他结点,直到B中结点遍历完,都相同时,则B是A的子树

3.对应位置的结点不相同时,退出继续在A中寻找和B的根节点相同的结点,重复步骤,直到有任何一棵二叉树为空退出

首先需要判断是否为空

对每一个结点判断是否是子树, 其中isSubtree用来判断t1和t2是否是相同子树。
当t2NULL时说明能够遍历到叶子,则t2是t1子树。
当t1
NULL&&t2!=NULL则t2还没遍历完,t1就结束了,那么肯定不是子树。
如果这两个结点t1 t2的值相同,则要比较他们的左右子树,只要有一个子树不同那么就没有父子关系。
如果值不相同直接返回FALSE;
用HasSubtree来选择哪两个结点来进行选择。
只要两个结点有一个是空结点,不需要比较,返回NULL。
这个结点或者这个结点的左右子树,只要有一个满足与被比较结点是有相同的子树(也就是返回true)那么就应该返回true作为结果。
首先在树A中找到和树B根节点值相同的节点R;
然后判断树A中以R为根节点的子树是否包含了和树B一样的结构。

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def HasSubtree(self, pRoot1, pRoot2):
        if pRoot1==None or pRoot2==None: #如果p1,p2的根节点都是空,则返回FALSE
            return False
        result=False
        if pRoot1.val==pRoot2.val: #如果p1的根节点和p2的根节点相同,判断是否是子树
            result=self.isSubtree(pRoot1,pRoot2)
        if result==False: #如果不是,则把p1的左子树当做根节点,去判断,再找不到,把p1的右子树当做根节点判断,
            result=self.HasSubtree(pRoot1.left,pRoot2)|self.HasSubtree(pRoot1.right,pRoot2)
        return result
    def isSubtree(self,root1,root2):
        #该函数判断在找到和子树根节点相同的节点之后,判断其余节点是否相同
        if root2==None: #如果p2的其余节点时空,说明只有一个根节点和p1相同,返回true
            return True
        if root1==None: #如果p1的其余节点为空,说明不是其子树,返回false
            return False
        if root1.val==root2.val: #如果其余节点有相同的,再比较左右子树的节点
            return self.isSubtree(root1.left,root2.left)& self.isSubtree(root1.right,root2.right)
        return False

题目3----二叉树镜像

操作给定的二叉树,将其变换为源二叉树的镜像。
在这里插入图片描述
思路:先找到根节点 根节点遍历左右子树,左右子树交换位置,
将左子树和右子树交换
递归思想,先交换根节点的左右子树的位置,然后向下递归,把左右子树的根节点作为下次循环的根节点

class Solution:
    # 返回镜像树的根节点
    def Mirror(self, root):
        if root==None:
            return 
        if root.left==None and root.right==None:
            return 
       #这三步交换根节点的左右树,交换的树,而不单单是节点
        tmp=root.right
        root.right=root.left
        root.left=tmp
        if root.left is not None:
            self.Mirror(root.left)
        if root.right is not None:
            self.Mirror(root.right)

题目4–从上往下打印二叉树

从上往下打印出二叉树的每个节点,同层节点从左至右打印。

思路:即层次遍历
二叉树的层次遍历 先计算出根节点的左右子树,借助一个队列,再循环递归
思路还是很清晰的,使用两个队列一个存放节点,一个存放值。先将根节点加入到队列中,然后遍历队列中的元素,遍历过程中,访问该元素的左右节点,再将左右子节点加入到队列中来

广搜的套路就是用一个队列保存将要搜索的这一层的元素,然后逐个搜索;
1、将第一个元素加入队列
2、队列不为空时取队首元素
3、将下一层元素加入队尾
4、调到第二步,直到队列为空
root 是根节点
这里为什么不能使用一个数组就可以,算法可以通过,但是计算量很大

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    # 返回从上到下每个节点值列表,例:[1,2,3]
    def PrintFromTopToBottom(self, root):
        if root is None:
            return []
        queue=[]
        result=[]
        queue.append(root)
        while len(queue)>0:
            root=queue.pop(0)
            result.append(root.val)
            if root.left is not None:
                queue.append(root.left)
            if root.right is not None:
                queue.append(root.right)
        return result

题目5–二叉搜索树的后续遍历

输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。

思路:> 思路:

  1. 二叉树的后序遍历 先左节点再是右节点,最后是根节点
    2.二叉搜索树是对一个有序数组进行二分查找形成的搜索树,它指一棵空树或者具有下列性质的二叉树:
    若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值; 若任意节点的右子树不空,则右子树上所有节点的值均大于它的根节点的值;
    任意节点的左、右子树也分别为二叉查找树;

以下图二叉树为例,我们都知道对二叉搜索树进行中序遍历可以还原为一个有序数组,而图中二叉树后序遍历结果为[3,2,4,6,8,7,5]。接下来分析一下这个数组的规律。首先按照后序遍历的性质,数组的最后一个元素即是整个二叉树的根结点。另外按照搜索二叉树的前两条性质,左子树均小于根,右子树均大于根。左右子树部分同样符合整个规律,所以我们可以递归实现数组的判断。
在这里插入图片描述

# -*- coding:utf-8 -*-
class Solution:
    def VerifySquenceOfBST(self, sequence):
        if len(sequence)==0:
            return False
        else:
            root=sequence[-1]
            del sequence[-1]
            lefttree=[]
            righttree=[]
            splitindex=-1
            for i in range(len(sequence)):
                if sequence[i]<root:
                    lefttree.append(sequence[i])
                    splitindex=i
                else:
                    break  #要注意返回条件
            for i in range(splitindex+1,len(sequence)):
                if sequence[i]>root:
                    righttree.append(sequence[i])
                else:
                    return False
            if len(lefttree)<=1:
                left=True
            else:
                left=self.VerifySquenceOfBST(lefttree)
            if len(righttree)<=1:
                right=True
            else:
                right=self.VerifySquenceOfBST(righttree)
            return left and right
                      

题目6-二叉树和为某一值的路径

输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)

思路:递归

首先要理解题意,是从根节点往子节点连。

1、如果只有根节点或者找到叶子节点,我们就把其对应的val值返回

2、如果不是叶子节点,我们分别对根节点的左子树、右子树进行递归,直到找到叶子结点。然后遍历把叶子结点和父节点对应的val组成的序列返回上一层;如果没找到路径,其实也返回了序列,只不过是[]

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    # 返回二维列表,内部每个列表表示找到的路径
    def FindPath(self, root, expectNumber):
        result=[]
        if root is  None:
            return result
        if not root.left and not root.right and root.val==expectNumber:
            return [[root.val]]
        else:
            left=self.FindPath(root.left,expectNumber-root.val)
            right=self.FindPath(root.right,expectNumber-root.val)
        for item in left+right:
            result.append([root.val]+item)
        return result
            

题目7–二叉搜索树与双向链表

输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
思路:先中序遍历,将所有的节点保存到一个列表中。对这个list[:-1]进行遍历,每个节点的right设为下一个节点,下一个节点的left设为上一个节点。
当前结点指向左指针指向前驱结点
前驱结点右指针指向当前结点

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def Convert(self, pRootOfTree):
        # write code here
        if not pRootOfTree:return
        self.arr = []
        self.midTraversal(pRootOfTree)
        for i,v in enumerate(self.arr[:-1]):
            v.right = self.arr[i + 1]
            self.arr[i + 1].left = v
        return self.arr[0]
    def midTraversal(self, root):
        if not root: return
        self.midTraversal(root.left)
        self.arr.append(root)  #这里为什么加上这么一句话
        self.midTraversal(root.right)

题目8-二叉树的深度

输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
思路:直接使用递归方法

class Solution:
    def TreeDepth(self, pRoot):
        # write code here
        # 使用层次遍历
        # 当树为空直接返回0
        if pRoot is None:
            return 0
        # 方法2:使用递归
        # 如果该树只有一个结点,它的深度为1.如果根节点只有左子树没有右子树,
        # 那么树的深度为左子树的深度加1;同样,如果只有右子树没有左子树,
        # 那么树的深度为右子树的深度加1。如果既有左子树也有右子树,
        # 那该树的深度就是左子树和右子树的最大值加1.
        count = max(self.TreeDepth(pRoot.left), self.TreeDepth(pRoot.right)) + 1
        return count
```

可采用层次遍历,或者前序遍历

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def TreeDepth(self, root):
        if root is None:
            return
        res = []
        # 层数
        count = 0
        # 如果根节点为空,则返回空列表
        if root is None:
            return count
        # 模拟一个队列储存节点
        q = []
        # 首先将根节点入队
        q.append(root)
        # 列表为空时,循环终止
        while len(q) != 0:
            # 使用列表存储同层节点
            tmp = []
            # 记录同层节点的个数
            length = len(q)
            for i in range(length): ###注意这个
                # 将同层节点依次出队
                r = q.pop(0)
                if r.left is not None:
                    # 非空左孩子入队
                    q.append(r.left)
                if r.right is not None:
                    # 非空右孩子入队
                    q.append(r.right)
                tmp.append(r.val)
            if tmp:
                count += 1  # 统计层数
            res.append(tmp)
        return count

题目9–平衡二叉树

输入一棵二叉树,判断该二叉树是否是平衡二叉树。

平衡二叉树的定义是任何节点的左右子树高度差都不超过1的二叉树。

按照定义,很容易得出获得左右子树高度,然后判断。递归写法。

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def IsBalanced_Solution(self, pRoot):
        if not pRoot: return True
        left = self.TreeDepth(pRoot.left)
        right = self.TreeDepth(pRoot.right)
        if abs(left - right) > 1:
            return False
        return self.IsBalanced_Solution(pRoot.left) and self.IsBalanced_Solution(pRoot.right)

    def TreeDepth(self, pRoot):
        if not pRoot: return 0
        left = self.TreeDepth(pRoot.left)
        right = self.TreeDepth(pRoot.right)
        return max(left, right) + 1

题目10-二叉树的下一个结点

给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
思路:
中序遍历–即左-根-右
结合图,我们可发现分成两大类:1、有右子树的,那么下个结点就是右子树最左边的点;(eg:D,B,E,A,C,G) 2、没有右子树的,也可以分成两类,a)是父节点左孩子(eg:N,I,L) ,那么父节点就是下一个节点 ; b)是父节点的右孩子(eg:H,J,K,M)找他的父节点的父节点的父节点…直到当前结点是其父节点的左孩子位置。如果没有eg:M,那么他就是尾节点
在这里插入图片描述
分析二叉树的下一个节点,一共有以下情况:
1.二叉树为空,则返回空;
2.节点右孩子存在,则设置一个指针从该节点的右孩子出发,一直沿着指向左子结点的指针找到的叶子节点即为下一个节点(如B);
3.节点不是根节点。如果该节点是其父节点的左孩子,则返回父节点入D;否则继续向上遍历其父节点的父节点,重复之前的判断,返回结果(如图J一直向上查到找到B(B为其父节点的左子结点,借用第二步,则 B的父节点A为下一结点)

# -*- coding:utf-8 -*-
# class TreeLinkNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
#         self.next = None
class Solution:
    def GetNext(self, pNode):
        # write code here
        if pNode.right:#有右子树
            p=pNode.right
            while p.left:
                p=p.left
            return p
        while pNode.next:#无右子树,则找第一个当前节点是父节点左孩子的节点
            if(pNode.next.left==pNode):
                return pNode.next
            pNode = pNode.next#沿着父节点向上遍历
        return  #到了根节点仍没找到,则返回空

题目11.—对称的二叉树

请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。
思路:
先把此二叉树对称处理,再和原来比较。
思路:首先根节点以及其左右子树,左子树的左子树和右子树的右子树相同

  • 左子树的右子树和右子树的左子树相同即可,采用递归
  • 非递归也可,采用栈或队列存取各级子树根节点
  • 键还是知道怎么样才能判断一个
    二叉树是否对称,只要采用前序、中序、后序、层次遍历等任何一种遍历方法,分为先左后右和先
    右后左两种方法,只要两次结果相等就说明这棵树是一颗对称二叉树。
# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def isSymmetrical(self, pRoot):
        if pRoot is None:
            return True
        return self.Traversal(pRoot.left,pRoot.right)
    def Traversal(self,left, right):
        if left is None and right is None:
            return True
        elif left and right and left.val ==right.val:
            return self.Traversal(left.left,right.right) and self.Traversal(left.right,right.left)#注意这里
        else:
            return False    

题目12.—按照之字形打印二叉树

请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。
思路:
可以参考那个计算层数的层次遍历
或者类似层次遍历,加个判断条件,奇数层正序遍历,偶数层倒序遍历队列
Python 解法,用递归遍历每一层节点,并按层数为列表的索引值存为子列表
#然后把奇数索引的子列表倒序即可

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def Print(self, pRoot):
        if pRoot is  None:
            return []
        queue=[]
        queue.append(pRoot)#把根节点存储在队列
        result=[]#存储树有多少层,1,2,3,4之类
        while len(queue)!=0:
            res=[] #存储每层节点
            nextStack=[] #存储左右子树节点
            for i in queue:
                res.append(i.val)
                if i.left:
                    nextStack.append(i.left)
                if i.right:
                    nextStack.append(i.right)
            queue=nextStack
            result.append(res) #这里得到是每一层,和每一层对应的节点
        returnResult=[]
        for i, v in enumerate(result):
            if i%2==0:
                returnResult.append(v)
            else:
                returnResult.append(v[::-1])
        return returnResult
                  

题目13–把二叉树打印成多行

从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。
思路:在上一题的基础上,去掉那个奇偶层判断即可

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def Print(self, pRoot):
        if pRoot is  None:
            return []
        queue=[]
        queue.append(pRoot)#把根节点存储在队列
        result=[]#存储树有多少层,1,2,3,4之类
        while len(queue)!=0:
            res=[] #存储每层节点
            nextStack=[] #存储左右子树节点
            for i in queue:
                res.append(i.val)
                if i.left:
                    nextStack.append(i.left)
                if i.right:
                    nextStack.append(i.right)
            queue=nextStack
            result.append(res) #这里得到是每一层,和每一层对应的节点
        return result

题目14–序列化二叉树

请实现两个函数,分别用来序列化和反序列化二叉树
思路:对于序列化:使用前序遍历,递归的将二叉树的值转化为字符,并且在每次二叉树的结点
不为空时,在转化val所得的字符之后添加一个’ , '作为分割。对于空节点则以 ‘#’ 代替。
2. 对于反序列化:按照前序顺序,递归的使用字符串中的字符创建一个二叉树(特别注意:
在递归时,递归函数的参数一定要是char ** ,这样才能保证每次递归后指向字符串的指针会
随着递归的进行而移动!!!)

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def __init__(self):
        self.flag = -1
         
    def Serialize(self, root): #这个可以看懂
        # write code here
        if root is None:
            return '#,'
        return str(root.val)+','+self.Serialize(root.left)+self.Serialize(root.right)
         
    def Deserialize(self, s): #这个看不懂
        self.flag += 1
        l = s.split(',')
         
        if self.flag >= len(s):
            return None
        root = None         
        if l[self.flag] != '#':
            root = TreeNode(int(l[self.flag]))
            root.left = self.Deserialize(s)
            root.right = self.Deserialize(s)
        return root
# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def Serialize(self, root):
        ret=[]
        if root is None:
            return '#'
        ret.append(str(root.val))
        l=self.Serialize(root.left)
        ret.append(l)
        r=self.Serialize(root.right)
        ret.append(r)
        return ','.join(ret)

    def Deserialize(self, s):
        serialize=s.split(',')
        tree,sp=self.deserialize(serialize,0)
        return tree
    def deserialize(self, s, sp):
        if sp >= len(s) or s[sp] == "#":
            return None, sp + 1
        node = TreeNode(int(s[sp]))
        sp += 1
        node.left, sp = self.deserialize(s, sp)
        node.right, sp = self.deserialize(s, sp)
        return node, sp

题目15 —二叉搜索树的第k个节点

给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为4。

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    # 返回对应节点TreeNode
    def KthNode(self, pRoot, k):
        self.res=[]
        self.dfs(pRoot)
        if 0<k<=len(self.res):
            return self.res[k-1] 
        else:
            return None
    def dfs(self,root):
        if not root:return
        self.dfs(root.left)
        self.res.append(root)
        self.dfs(root.right)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值