剑指Offer——二叉搜索树与双向链表

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

我的想法很简单,分解&递归。从下至上构造,将其化为有序链表。构造过程中,若节点有右孩子,则左旋(或右旋),将右(左)孩子作为父节点的新左孩子,最后父节点连接左右子树(因左子树所有数大小都小于右子树任意节点,所以父节点必然在中间),作为新的左(右)孩子。
我以下面的树做例子讲下思路。
这里写图片描述

第一次分解

首先判断root是否是NULL,不为NULL,则递归分解。
递归的结果会将其分解为两个子树:
这里写图片描述

第二次分解

仍然不是叶子节点,继续分解
这里写图片描述
分解后发现1、3为叶子节点,从下往上进行构造链表。
因为其父节点有左儿子,所以需要进行节点更换,将第一次分解后的树变为如下结构:
这里写图片描述
1为新的根节点。
同样方法处理右子树。
得到右子树如下:
这里写图片描述
整体结构:
这里写图片描述

将4按照同样方法来进行处理,令左儿子作为新的根节点,将原根节点接在3的后面,同时连接到5上。
这样1 -> 2 ->3 ->4 ->5 这样的链表就构造完成了。

代码

这个代码我是按照左移数值增大这么写的,但牛客网要求右移增大,所以在代码的最后我遍历翻转了下指针以达到要求:

class Solution {
public:
    TreeNode* Convert(TreeNode* pRootOfTree)
    {
        static int Counter = 0;Counter ++;//(1)
        TreeNode* pRet = pRootOfTree;
        if(pRootOfTree != NULL)
        {
            TreeNode* pLeft = Convert(pRootOfTree->left);//返回最小值节点
            TreeNode* pRight = Convert(pRootOfTree->right);//返回最小值节点
            if(pLeft != NULL)//需要更换返回的Root节点
            {
                pRet = pLeft;
                while(pLeft->left)
                {
                    pLeft = pLeft->left;
                }
                pLeft->left = pRootOfTree;
                if(pRight)
                    pRight->right = pRootOfTree;
                pRootOfTree->left = pRight;
                pRootOfTree->right = pLeft;
            }
            else if(pRight != NULL)
            {
                pRet->left = pRight;
                pRight->right = pRet;
            }
            pRet->right = NULL;
        }
        Counter--;//(2)
        if(Counter == 0)//(1),(2),包括此处为翻转左右子树指针
        {
            TreeNode* pCurr = pRet;
            while(pCurr)
            {
                TreeNode* pTemp = pCurr->left;
                pCurr->left = pCurr->right;
                pCurr->right = pTemp;
                pCurr = pCurr->right;
            }
        }
        return pRet;
    }
};

猜你喜欢

转载自blog.csdn.net/sunhaobo1996/article/details/79567127
今日推荐