剑指36 二叉搜索书与双向链表
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。
为了让您更好地理解问题,以下面的二叉搜索树为例:
我们希望将这个二叉搜索树转化为双向循环链表。链表中的每个节点都有一个前驱和后继指针。对于双向循环链表,第一个节点的前驱是最后一个节点,最后一个节点的后继是第一个节点。
下图展示了上面的二叉搜索树转化成的链表。“head” 表示指向链表中有最小元素的节点。
特别地,我们希望可以就地完成转换操作。当转化完成以后,树中节点的左指针需要指向前驱,树中节点的右指针需要指向后继。还需要返回链表中的第一个节点的指针。
LeetCode这一题和书上稍有不同,LeetCode需要把链表头尾链接起来。
一开始以为直接按中序遍历调整一下指针就可以了,但是并不是这样,每个节点左侧连接的是左子树的最大值节点,右侧链接的是右子树的最小值节点,并不一定是原本的左右子节点。
这个题采用递归的方法,先处理好左子树,连接当前节点和左子树;再处理好右子树,链接当前节点和右子树。最后连接头尾。
分别定义两个函数,处理左子树和右子树。处理左子树函数需要返回处理后的链表的最大值,即链表尾;处理右子树函数需要返回处理后的链表的最小值,即链表头。
注意在当前节点连接到了左子节点或者右子节点后,子节点也要反向连接到当前节点。如果没有这一步,那么所有叶子节点的两个指针都是null,这样链表就断开了,一开始犯了这个错误。
不要忘记处理根节点为空的情况。
1 /* 2 // Definition for a Node. 3 class Node { 4 public: 5 int val; 6 Node* left; 7 Node* right; 8 9 Node() {} 10 11 Node(int _val) { 12 val = _val; 13 left = NULL; 14 right = NULL; 15 } 16 17 Node(int _val, Node* _left, Node* _right) { 18 val = _val; 19 left = _left; 20 right = _right; 21 } 22 }; 23 */ 24 class Solution { 25 public: 26 Node* treeToDoublyList(Node* root) { 27 if(root==nullptr) 28 return root; 29 if(root->left!=nullptr){ 30 root->left=convert_left(root->left); 31 root->left->right=root; 32 } 33 if(root->right!=nullptr){ 34 root->right=convert_right(root->right); 35 root->right->left=root; 36 } 37 Node* leftside=root,*rightside=root; 38 while(leftside->left!=nullptr) 39 leftside=leftside->left; 40 while(rightside->right!=nullptr) 41 rightside=rightside->right; 42 leftside->left=rightside; 43 rightside->right=leftside; 44 45 return leftside; 46 } 47 48 Node* convert_left(Node* cur_node){//返回该子树中最大的节点 49 if(cur_node->left!=nullptr){ 50 cur_node->left=convert_left(cur_node->left); 51 cur_node->left->right=cur_node; 52 } 53 if(cur_node->right!=nullptr){ 54 cur_node->right=convert_right(cur_node->right); 55 cur_node->right->left=cur_node; 56 } 57 while(cur_node->right!=nullptr) 58 cur_node=cur_node->right; 59 return cur_node; 60 } 61 62 Node* convert_right(Node* cur_node){//返回该子树中最小的节点 63 if(cur_node->left!=nullptr){ 64 cur_node->left=convert_left(cur_node->left); 65 cur_node->left->right=cur_node; 66 } 67 if(cur_node->right!=nullptr){ 68 cur_node->right=convert_right(cur_node->right); 69 cur_node->right->left=cur_node; 70 } 71 while(cur_node->left!=nullptr) 72 cur_node=cur_node->left; 73 return cur_node; 74 } 75 };