剑指 36 二叉搜索树与双向链表【二叉搜索树】【中序遍历】【双向链表】

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

全部刷题与学习记录

【C++刷题学习笔记目录】

【C++百万并发网络通信-笔记目录】

原题目

题目地址:剑指 Offer 36. 二叉搜索树与双向链表

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

	4
   / \
  2   5
 / \
1   3

考查知识点

分治法、中序遍历


好的解法

首先是剑指上的解法在代码上没怎么看懂,在力扣上找了这篇题解。

思路:二叉搜索树每个节点有leftright两个子节点,并且满足left->val < root->val < right->val。在双向链表中每个节点具有prenext两个指针,因为题目规定**“排序”**的原因,同样满足pre->val < root->val < right->val。因此将left作为pre,将right作为next

因为满足左-根-右,所以必然和中序遍历建立关系。

规定头结点head与尾指针tailhead一定是双向链表中最左端的节点,tail一定是最右端的节点。在中序遍历开始后,root会一直走到二叉搜索树的左下端(即1处),即双向链表的头结点,此时tail=nullptr,有head=root, 我们再让tail=root。然后root会返回到父节点2处(此时root=2,tail=1),这时我们就写 tail -> right = root;root -> left = tail;然后再更新tail=root,一直重复。

只看文字描述还是太抽象,一定要结合程序在纸上画一下

注意递归函数inorder的调用顺序与函数的实际处理部分(不包含递归的部分)就是体现中序遍历的地方

//题解:https://leetcode-cn.com/problems/er-cha-sou-suo-shu-yu-shuang-xiang-lian-biao-lcof/solution/zi-jie-ti-ku-jian-36-zhong-deng-er-cha-sou-suo-shu/
class Solution {
    
    
private:
    Node* head, *tail;
public:
    Node* treeToDoublyList(Node* root) {
    
    
        if(!root) {
    
    
            return nullptr;
        }

        inorder(root); // 构造出链表的所有结构,除了头连尾和尾连头的两个指针
        head -> left = tail; // 补上头连尾
        tail -> right = head; // 补上尾连头

        return head; // 返回头
    }
    void inorder(Node* root) {
    
    
        if(!root) {
    
    
            return;
        }

        inorder(root -> left); // 左

        if(!tail) {
    
    
            head = root; // 当tail还不存在,也就是root此时在整个BST的最左边的节点,这个节点就是head
        }
        else {
    
    
            tail -> right = root; // 前一个节点的right是当前节点
            root -> left = tail; // 当前节点的left是前一个节点
        }
        tail = root; // 将前一个节点更新为当前节点(所以到最后,tail就会挪到整个BST的最右边的节点,这个节点就是链表的尾节点)

        inorder(root -> right); // 右
    }
};

l就会挪到整个BST的最右边的节点,这个节点就是链表的尾节点)

    inorder(root -> right); // 右
}

};


猜你喜欢

转载自blog.csdn.net/weixin_44484715/article/details/112535955