Leetcode 剑指 Offer 36. 二叉搜索树与双向链表
题目
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。
为了让您更好地理解问题,以下面的二叉搜索树为例:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210222094445177.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzg5MTc3NQ==,size_16,color_FFFFFF,t_70)
我们希望将这个二叉搜索树转化为双向循环链表。链表中的每个节点都有一个前驱和后继指针。对于双向循环链表,第一个节点的前驱是最后一个节点,最后一个节点的后继是第一个节点。
下图展示了上面的二叉搜索树转化成的链表。“head” 表示指向链表中有最小元素的节点。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210222094457490.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzg5MTc3NQ==,size_16,color_FFFFFF,t_70)
特别地,我们希望可以就地完成转换操作。当转化完成以后,树中节点的左指针需要指向前驱,树中节点的右指针需要指向后继。还需要返回链表中的第一个节点的指针。
思路
- 二叉搜索树的中序遍历是有序的序列, 所以要想把一棵BST转换成有序的链表, 需要借助于中序遍历
- 我们需要设置2个指针, head记录这个链表的头部, pre记录每次遍历的前驱指针
- 在中序遍历的框架中, 当pre == nullptr时候, 此时就是位于有序链表的头部位置, 之后就是设置双向链表的左右指向即可
- 注意, 本题双向链表还是循环的, 所以最后遍历完成之后pre实际上位于最右侧的那个节点, 我们需要将head和pre做一个相连此时完成循环
代码 —— c++
/*
// Definition for a Node.
class Node {
public:
int val;
Node* left;
Node* right;
Node() {}
Node(int _val) {
val = _val;
left = NULL;
right = NULL;
}
Node(int _val, Node* _left, Node* _right) {
val = _val;
left = _left;
right = _right;
}
};
*/
class Solution {
private:
Node* head = NULL;
Node* pre = NULL;
public:
void dfs(Node* root) {
if (!root) return;
// left
dfs(root->left);
// mid
if (!pre) {
head = root;
} else {
pre->right = root;
}
root->left = pre;
pre = root;
// right
dfs(root->right);
}
Node* treeToDoublyList(Node* root) {
if (!root) return nullptr;
dfs(root);
pre->right = head;
head->left = pre;
return head;
}
};