【剑指Offer】26、二叉搜索树与双向链表

发布时间 2023-08-14 23:52:37作者: bujidao1128

题目描述:

输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。

解题思路:

首先要理解此题目的含义,在双向链表中,每个结点都有前后两个指针;二叉树中,每个结点都有两个指向子结点的左右指针,同时,二叉搜索树树也是一种排序的数据结构。因此,从结构上看,双向链表的前后指针和二叉搜索树的左右指针结构相似,因此,可以实现互相之间的转换。

首先,根据二叉搜索树的特点,左结点的值<根结点的值<右结点的值,据此不难发现,使用二叉树的中序遍历得到的数据序列就是递增的排序顺序。因此,首先确定应该采用中序遍历方法。

接下来,可以根据下图,将树分为三个部分,值为10的根结点、根为6的左子树和根为14的右子树。不难看出以下规律:根据中序遍历的顺序,当我们遍历到根结点时,它的左子树已经转换为一个排好序的双向链表,并且链表最后一个结点是左子树值最大的结点,我们把这个值最大(8)的结点同根结点链接起来,10就成了最后一个结点,接着遍历右子树,将根结点同右子树中最小的结点链接起来。

很明显,左右子树具有和原问题相同的结构,因此直接利用递归即可实现。

举例:

编程实现(Java):

public class Solution {
    public TreeNode Convert(TreeNode pRootOfTree) {
        //根据中序遍历采用递归依次实现
        if(pRootOfTree==null)
            return null;
        TreeNode curEndoflink=null;
        TreeNode root=pRootOfTree;
        Convert(root,curEndoflink);
        
        while(pRootOfTree!=null && pRootOfTree.left!=null){ //链表头是最左边
            pRootOfTree=pRootOfTree.left;
        }
        return pRootOfTree;
    }
    //curEndoflink保存的是当前已经排好的链表的最后一个节点
    public TreeNode Convert(TreeNode pRootOfTree,TreeNode curEndoflink){
        if(pRootOfTree==null)
            return null;
        TreeNode root=pRootOfTree;
        if(root.left!=null) //将左子树构建为链表
            curEndoflink=Convert(root.left,curEndoflink);
        
        //将根接在左子树的链表之后
        root.left=curEndoflink;
        if(curEndoflink!=null)
            curEndoflink.right=root;
        curEndoflink=root;  //引用改变值,需要return
        
        if(root.right!=null) //将右子树构建为链表
            curEndoflink=Convert(root.right,curEndoflink);
        
        return curEndoflink;
        
    }
}