題目描述
輸入一棵二叉搜索樹,將該二叉搜索樹轉換成一個排序的雙向鏈表。要求不能創建任何新的結點,只能調整樹中結點指針的指向。
解法一:
因題目中不允許創建任何新的結點,故可以創建一個數組來存放所有的結點。
即通過中序遍歷求出排序列表,然後遍歷數組,依次爲每個結點的左右指針賦值。
//中序遍歷
void in_order(TreeNode* root,vector<TreeNode*> &v){
if(root != NULL){
in_order(root->left,v);
v.push_back(root);
in_order(root->right,v);
}
}
//二叉搜索樹與雙向鏈表
TreeNode* Convert(TreeNode* pRootOfTree){
if(pRootOfTree==NULL){
return NULL;
}
vector<TreeNode*> v;
in_order(pRootOfTree,v);
TreeNode* p = v[0];
for(int i = 1;i < v.size();i++){
p->right = v[i];
v[i]->left = p;
p = v[i];
}
return v[0];
}
解法二:
通過二叉搜索樹的性質,可知,雙向鏈表的左指針指向的結點爲該結點的左子樹的最右邊的結點,右指針指向的結點爲該結點的右子樹的最左邊的結點。
故可以通過遞歸的方式來實現。
//找最右結點
TreeNode* find_right(TreeNode* root){
while(root->right){
root = root->right;
}
return root;
}
//二叉搜索樹與雙向鏈表
TreeNode* Convert(TreeNode* pRootOfTree){
if(pRootOfTree == NULL){
return NULL;
}
TreeNode* leftNode = Convert(pRootOfTree->left);//找到最左邊結點
TreeNode* rightNode = Convert(pRootOfTree->right);
TreeNode* head = leftNode;//鏈表的頭部
if(leftNode){
leftNode = find_right(leftNode);
}else{
head = pRootOfTree;
}
//構造雙向鏈表
pRootOfTree->left = leftNode;
pRootOfTree->right = rightNode;
if(leftNode){
leftNode->right = pRootOfTree;
}
if(rightNode){
rightNode->left = pRootOfTree;
}
return head;
}