通用算法 - [树结构] -二叉树的一些基本操作(三)

1、前言

数组、链表、二叉树、动态规划、栈与队列是面试中常考的知识点,而在这几个知识点中,二叉树属于难度比较大的部分,因此在这里总结一下二叉树常考的操作,包括:
(1)二叉树的递归遍历;
(2)二叉树的非递归遍历;
(3)求二叉树叶子节点的个数;
(4)求二叉树的深度;
(5)在二叉树中查找某颗子树;
(6)求二叉树中和为某个值的路径;
(7)求二叉树中的最大路径和;
(8)二叉树的镜像;
(9)判断某个序列是否是二叉搜索树的后序遍历序列;
(10)二叉搜索树和双向链表的相互转换;
(11)树中两个结点的最近祖先;
(12)二叉树搜索树的插入与删除;
(13)堆的插入与删除;
(14)判断一棵树是不是平衡二叉树;
(15)平衡二叉树的调整;

2、二叉树的基本操作

(9)判断某个序列是否是二叉搜索树的后序遍历序列
基本思路:可以采用倒推的方法,如果一个序列是二叉搜索树的后序遍历序列,那么该序列会有什么样的特征?
如果一个序列是二叉树的后序遍历序列,那么它一定具有以下性质:
(1)序列可以根据序列的最后一个数number划分为两部分,一部分大于number,记为A;另一部分小于number,记为B;且A一定在B的前面,A和B中的长度可以为0;
(2)序列A、B同样遵循性质(1);

def IsBackOrderSeq(seq,start,end):

	if len(seq) <= 0:
	
		return False
		
    length = end - start + 1

    if length == 1:

        return True

    greater_index = start

    for i in range(start,end):

        if seq[i] < seq[end]:

            greater_index += 1
        
    for j in range(greater_index,end):

        if seq[j] < seq[end]:

            return False

    front_isback = True

    back_isback = True

    if greater_index - 1 >= start:

        front_isback = IsBackOrderSeq(seq,start,greater_index - 1)

    if greater_index <= end - 1:

        back_isback = IsBackOrderSeq(seq,greater_index,end - 1)


    return front_isback and back_isback

        

(10)二叉搜索树和双向链表的相互转换
输入一棵二叉排序树,将该二叉排序树转换成排序的双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。
如下图所示:
通用算法 - [树结构] -二叉树的一些基本操作(三)_第1张图片
基本思路:我们把二叉树搜索树中每个节点的左指针作为双向链表中的前向指针,右指针看成后向指针。同时将二叉树分为三个部分,左子树,根节点,和右子树。在转换时,只需将根节点与左子树中的最大节点链接,然后再将根节点与右子树的最小节点连接。
具体地,使用指针pLasNodeInList来保存已经转换好的排序双向链表的尾节点,再使用中序遍历二叉树中的每一个节点时,不断地将当前遍历节点插入到双向链表的末尾。

简单来说,就是不断地在排序的双向链表末尾pLastNodeInList插入中序遍历的当前节点。
代码实现:

pLastNodeInList = None

def ConvertNode(rootnode):

    if rootnode == None:

        return


    ConvertNode(rootnode.left)
    
    
    global pLastNodeInList
    
    rootnode.left = pLastNodeInList

    if pLastNodeInList != None:

        pLastNodeInList.right = rootnode

    pLastNodeInList = rootnode
    

    ConvertNode(rootnode.right)
    

(11)树中两个结点的最近祖先

基本思想

利用后序遍历实现;
对于当前遍历节点curnode,如果当前节点为null或等于A、或等于B,直接返回该节点;
先处理curnode的左右子树,左子树返回left,右子树返回right,判断left和right;
1)如果left、right都不为空,则说明在curnode的左子树中找到了A或B,curnode的右子树中也找到了A或B,curnode为A和B的首次相遇点,也是A和B的最近祖先,直接返回curnode;
2)如果left和right中一个为null,另一个不为null,说明不为空的节点是A和B中的一个,直接返回不为空的节点;
3)如果left、right都为空,说明以curnode为根的子树上没有发现A或B,返回null;
通用算法 - [树结构] -二叉树的一些基本操作(三)_第2张图片
代码实现

def getLatestAncestor(rootnode,node1,node2):

    if rootnode == None or rootnode.val == node1.val or rootnode.val == node2.val:

        return rootnode

    left = getLatestAncestor(rootnode.left,node1,node2)

    right = getLatestAncestor(rootnode.right,node1,node2)

    if left != None and right != None:

        return rootnode

    if left != None:

        return left

    if right != None:

        return right

    return None

(12)二叉树搜索树的插入与删除;
(13)堆的插入与删除;
(14)判断一棵树是不是平衡二叉树;
(15)平衡二叉树的调整;
关于上述问题,具体参考:通用算法 - [树结构] - 特殊的树结构

你可能感兴趣的:(数据结构与算法)