day37:二叉搜索树与双向链表(递归) and leetcode 36 二叉搜索树与双向链表

问题描述:
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。
要求不能创建任何新的结点,只能调整树中结点指针的指向。
注意:
需要返回双向链表最左侧的节点。例如,输入下图中左边的二叉搜索树,则输出右边的排序双向链表。
在这里插入图片描述
2021-5-7 晚上21:20 牛客网

巧妙地利用二叉搜索树的特点,二叉搜索树是树的中序遍历,就在中序递归遍历的基础上改了一点点,用一个pre指针保存中序遍历的前一个结点。因为是中序遍历,遍历顺序就是双线链表的建立顺序;
每一个结点访问时它的左子树肯定被访问过了,所以放心大胆的改它的left指针,不怕树断掉;同理,pre指向的结点保存的数肯定小于当前结点,所以其左右子树肯定都访问过了,所以其right指针也可以直接改。最后需要一直向左找到双向链表的头结点。

class Solution {
public:
    TreeNode* pre=NULL;
    TreeNode* convert(TreeNode* root) {
        dfs(root);
        while(root && root->left) root = root->left;
        return root;
    }
    void dfs(TreeNode* root){
        if(!root) return;
        dfs(root->left);

        root->left = pre;
        if(pre) pre->right = root;
        pre = root;

        dfs(root->right);
    }

    
};

二叉搜索树转化为有序的链表,采用的遍历方式是中序遍历,要求是调整节点指针的指向,只需要考虑如果是两个节点的话该如何调整指针的指向,前面节点的右指针指向后面的节点,后面的节点左指针指向前面的节点。更新时需要更新 tail 指针作为下一次的前面的节点。
考虑时不要把一整棵树考虑进去,太复杂了。参考链接

class Solution {
private:
        TreeNode* head=nullptr;//双链表的头结点
        TreeNode* tail=nullptr;//上一次遍历到的尾节点
public:
    void dfs(TreeNode* root)
    {
        if(!root) return;
        dfs(root->left);
        if(!tail) head=root;
        else
        {
            tail->right=root;
            root->left=tail;
        }
        
        tail= root;
        dfs(root->right);
    }
    TreeNode* Convert(TreeNode* root) {
        if(!root) return nullptr;
        dfs(root);
 
        return head;
    }
};

题目描述
剑指 Offer 36. 二叉搜索树与双向链表
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。为了让您更好地理解问题,以下面的二叉搜索树为例:
在这里插入图片描述我们希望将这个二叉搜索树转化为双向循环链表。链表中的每个节点都有一个前驱和后继指针。对于双向循环链表,第一个节点的前驱是最后一个节点,最后一个节点的后继是第一个节点。

下图展示了上面的二叉搜索树转化成的链表。“head” 表示指向链表中有最小元素的节点。特别地,我们希望可以就地完成转换操作。当转化完成以后,树中节点的左指针需要指向前驱,树中节点的右指针需要指向后继。还需要返回链表中的第一个节点的指针。
在这里插入图片描述

与上一题不同的是需要首尾链表相连,因此需要在中序遍历中过程中记录头结点和尾节点,头结点就是一开始遍历的时候的节点也就是pre节点为空的时候,尾节点是中序遍历末尾的节点,也就是遍历结束的节点指向的pre节点。
采用中序遍历递归,需要修改的是left节点和right节点,因为是中序遍历,那么遍历到root节点时,left节点已经遍历过了,pre指向的结点保存的数肯定小于当前结点,所以其左右子树肯定都访问过了,所以其right指针也可以直接改。

class Solution {
public:
    Node* pre=nullptr,*head;
    Node* treeToDoublyList(Node* root) {
        if(!root) return root;
        dfs(root);
        head->left = pre;
        pre->right = head;
        
        return head;
    }
    void dfs(Node* root)
    {
        if(!root) return;
        dfs(root->left);

        root->left = pre;
        if(pre) pre->right = root;
        else head=root;
        pre = root;

        dfs(root->right);
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值