二叉搜索树与双向列表
题目描述
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
题目分析
对于本题其实考察的是对于树的遍历,对于二叉搜索树,其性质之一是树的根节点大于左子树的节点而小于右子树的节点,而题目想要我们将一颗二叉搜索树转换成一个有序的的双向链表。
由树的遍历性质,我们可以知道当树进行中序遍历的时候,我们得到的序列便是我们想要得到的有序的序列。
但是题目要求的是不借助其他节点或者容器,只能通过指针的方式进行修改,所以我们不能通过中序遍历的方式将每一个几点读进一个容器里,然后再修改容器中指针的方向。
思路
1.我们先要在方法之外定义一个树节点的指针(该指针的作用是指向链表最后一个节点)。
2.我们在函数里判断根节点是否为空,如果为空则返回空,如果不为空,我们调用遍历函数。
3.进入遍历函数,我们定义一个currentNode指向当前节点,然后判断该节点的左指针域是否为空,如果不为空,则证明该节点还有左子树,我们接着调用遍历函数,直到该节点的左指针域为空。
4.当左指针域为空的时候则证明已经到达了二叉排序树的最左边的节点,也是最小的一个节点。
5.此时我们将lastNode赋给currentNode的左指针域(第一个节点的左指针域为空),然后判断lastNode是否为空,如果不为空,那么将lastNode的右指针域赋值currentNode。
6.接着我们将currentNode赋值给lastNode。
7.判断当前的节点是否有右子树,如果有我们还需要遍历其右子树,然后重复5,6。
8.递归结束,我们返回了最后一个节点的指针,此时我们需要的是第一个节点的指针,所以我们需要使用一个循环,只要head指针不为空并且指针的左指针域不为空,我们将指针的左指针域赋给该指针,指针往前移动1一个位置,直至到达第一个指针。
9.返回指针head。
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
TreeNode * lastNode=NULL;
public:
TreeNode* Convert(TreeNode* pRootOfTree)
{
if(pRootOfTree==NULL){
return NULL;
}
get(pRootOfTree);
TreeNode * head=lastNode;
while(head!=NULL && head->left!=NULL){
head=head->left;
}
return head;
}
void get(TreeNode * root){
TreeNode * currentNode=root;
if(root->left!=NULL){
get(root->left);
}
currentNode->left=lastNode;
if(lastNode!=NULL){
lastNode->right=currentNode;
}
lastNode=currentNode;
if(root->right!=NULL){
get(root->right);
}
}
};