输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树 中节点指针的指向。
为了让您更好地理解问题,以下面的二叉搜索树为例:
我们希望将这个二叉搜索树转化为双向循环链表。链表中的每个节点都有一个前驱和后继指针。对于双向循环链表,第一个节点的前驱是最后一个节点,最后一个节点的后继是第一个节点。
下图展示了上面的二叉搜索树转化成的链表。“head” 表示指向链表中有最小元素的节点。
特别地,我们希望可以就地完成转换操作。当转化完成以后,树中节点的左指针需要指向前驱,树中节点的右指针需要指向后继。还需要返回链表中的第一个节点的指针。
思路:首先看到这个顺序,就自然而言的想到了二叉搜索树的中序遍历。
然后,就应该要想到去获得当前节点的前驱节点,这个时候,一开想到的是通过函数的返回节点,后来写着写着发现比较麻烦,要考虑很多情况,不如用一个全局定义的头节点和前驱节点来实现。
/*
// 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 {
public:
Node* treeToDoublyList(Node* root) {
if(!root)return NULL;//首先先判断是否为空树,空树直接返回
get_list(root);
//当执行完具体的转换操作之后,head记录的就是最左边节点,pre记录的就是最右边节点
//下面将左右封闭,并返回头节点
head->left=pre;
pre->right=head;
return head;
}
private:
//基于中序遍历去做
Node* pre=NULL,*head=NULL;
void get_list(Node* root){
if(!root)return;//为NULL返回
//中序遍历,先处理左子树,再处理根节点,再处理右子树
get_list(root->left);
//先判断前驱是否为NULL,为空说明是头节点,不为空,让前驱的right指向当前节点
if(pre)pre->right=root;
else head=root;
//让当前节点的left指向前驱
root->left=pre;
//更新根节点
pre=root;
//处理右子树
get_list(root->right);
}
};