输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。
为了让您更好地理解问题,以下面的二叉搜索树为例:
我们希望将这个二叉搜索树转化为双向循环链表。链表中的每个节点都有一个前驱和后继指针。对于双向循环链表,第一个节点的前驱是最后一个节点,最后一个节点的后继是第一个节点。
下图展示了上面的二叉搜索树转化成的链表。“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) {
Node* list = nullptr;
LDR(root,&list);//此时我们得到的是最后的节点
Node* head = list;
while(head && head->left)head=head->left;//寻找首节点
if(head && list)//首尾链接
{
head->left = list;
list->right = head;
}
return head;
}
void LDR(Node* pNode,Node** list)//中序遍历链表链接
{
if(!pNode)return;
Node* pCurrent = pNode;
if(pCurrent->left)LDR(pCurrent->left,list);//寻找左结点
pCurrent->left = *list;//将根节点指向左侧最小节点
if(*list)(*list)->right = pCurrent;//双向链表
*list = pCurrent;//向右改变此时list的值
if(pCurrent->right)LDR(pCurrent->right,list);
}
};