剑指Offer-36:二叉搜索树与双向链表

题目 

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

思路

  二叉搜索树、排序链表,想到使用中序遍历。

  要实现双向链表,必须知道当前结点的前一个结点。根据中序遍历可以知道,当遍历到根结点的时候,左子树已经转化成了一个排序的链表了,根结点的前一结点就是该链表的最后一个结点(这个结点必须记录下来,将遍历函数的返回值设置为该结点即可),链接根结点和前一个结点,此时链表最后一个结点就是根结点了。再处理右子树,遍历右子树,将右子树的最小结点与根结点链接起来即可。左右子树的转化采用递归即可。

  大概思想再理一下:首先想一下中序遍历的大概代码结构(先处理左子树,再处理根结点,之后处理右子树),假设左子树处理完了,就要处理根结点,而根结点必须知道左子树的最大结点,所以要用函数返回值记录下来;之后处理右子树,右子树的最小结点(也用中序遍历得到)要和根结点链接。

//直接用中序遍历
public class Solution {
    TreeNode head = null;
    TreeNode realHead = null;//双向链表的头结点
    public TreeNode Convert(TreeNode pRootOfTree) {
    	if(pRootOfTree == null)
    		return ;
       //第一次运行时,它会使最左边叶子节点为链表第一个节点
        Convert(pRootOfTree.left);
        if (head == null) {
            head = pRootOfTree;
            realHead = pRootOfTree;
        } else {
            //把根节点插入到双向链表右边,rightHead向后移动
            head.right = pRootOfTree;  
            pRootOfTree.left = head;   
            head = pRootOfTree;  
        }
        //把右叶子节点也插入到双向链表(rightHead已确定,直接插入)
        Convert(pRootOfTree.right);
        //返回左边头结点
        return realHead;
    }
}

收获

  题目较复杂时,不要慌。这道题和中序遍历有关,把树分为三部分:根结点、左子树和右子树,思考在中序遍历中根结点应该如何处理,这是关键——要将左子树的最大结点、根结点、右子树的最小结点链接起来。左右子树的处理是相同的,因此采用递归。

猜你喜欢

转载自blog.csdn.net/qq_32534441/article/details/89390641