1.利用前驱后继
对于一个二叉树,可以将其分为左子树、根节点和右子树三部分。根据题目要求可知将BST化为一个排好序的双向链表实际上就是将其中序遍历序列对应的各个节点连接起来。同时还可以知道若根的左右子树非空,则根节点在链表中的前驱结点一定在其左子树中,后继结点一定在其右子树中。那么可以先找到并标记根节点的前驱和后继,然后连接。同时递归执行这一过程便能达到要求。
具体代码如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode *findPreNode(TreeNode *root){
TreeNode *p = root;
if(p -> left){
p = p -> left;
while(p -> right) p = p -> right;
return p;
}
else return NULL;
}
TreeNode *findSuccNode(TreeNode *root){
TreeNode *p = root;
if(p -> right){
p = p -> right;
while(p -> left) p = p -> left;
return p;
}
else return NULL;
}
TreeNode *change(TreeNode * root){
TreeNode *p = findPreNode(root); //记录前驱节点指针
TreeNode *q = findSuccNode(root); //记录后继节点指针
if(root -> left) change(root -> left);
if(root -> right) change(root -> right);
//将当前节点分别与其前驱节点和后继节点相连
root -> left = p;
if(p) p -> right = root;
root -> right = q;
if(q) q -> left = root;
return root;
}
TreeNode* convert(TreeNode* root) {
if(!root) return NULL;
change(root);
while(root -> left) root = root -> left;
return root;
}
};
2.中序遍历
可以发现对于一棵BST而言,中序遍历的当前节点与将要回溯的节点之间就是双向链表中相邻的关系。因此可以考虑通过中序遍历来直接完成BST到链表的转化。
具体代码如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode *change(TreeNode *root, TreeNode *&head, TreeNode *&tail){
if(!root) return NULL;
change(root -> left, head, tail);
if(!head){
head = tail = root;
}
else{
root -> left = tail;
tail -> right = root;
tail = root;
}
change(root -> right, head, tail);
return head;
}
TreeNode* convert(TreeNode* root) {
TreeNode *head = NULL, *tail = NULL; //注意这里要么在传参时使用指针引用要么将head和tail声明为全局变量
return change(root, head, tail);
}
};