整理自劍指Offer
一:題目描述
輸入一棵二叉搜索樹,將該二叉搜索樹轉換成一個排序的雙向鏈表。要求不能創建任何新的結點,只能調整樹中結點指針的指向。
二:代碼實現
在二叉樹中,每個節點都有兩個指向子結點的指針。在雙向鏈表中,每個節點也有兩個指針,他們分別指向前一個結點和後一個節點。
二叉搜索樹中左子結點的值都小於父結點的值,右子節點的值總是大於父子結點的值,如果採用中序遍歷的方式得到的就是排序好的序列。
現在需要解決的就是如何調整指針,使原先指向左子結點的指針調整爲鏈表中指向前一個結點的指針,原先指向右子節點的指針調整爲鏈表指向後一個節點的指針。
三:代碼實現
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
TreeNode* Convert(TreeNode* pRootOfTree)
{
//非遞歸版-利用棧來實現
//核心:修改當前遍歷結點與前一個遍歷結點的指針方向
if(pRootOfTree==NULL)
return NULL;
stack< TreeNode* > stackOfTree;
TreeNode* pNode=pRootOfTree;//指向要連接到鏈表的二叉搜索樹的結點
TreeNode* pPre=NULL;//指向雙向鏈表的最後一個結點
bool isFirstNode=true;
while(pNode!=NULL || !stackOfTree.empty()){
//指向以本次while循環R=pNode最左結點,因爲它是當前子樹的最小值
while(pNode!=NULL){
stackOfTree.push(pNode);
pNode=pNode->left;
}
//彈棧,彈出最左結點
pNode=stackOfTree.top();
stackOfTree.pop();
if(isFirstNode){
//如果它是鏈表第一個節點創建頭指針
pRootOfTree=pNode; //因爲根節點已經壓棧,所以不怕
pPre=pRootOfTree;
isFirstNode=false;
}
else{
//如果不是鏈表第一個節點,將當前節點鏈接到鏈表的後面
//鏈表最後結點的有指針指向當前節點
pPre->right=pNode;
//當前節點的左指針指向鏈表最後一個結點
pNode->left=pPre;
//pPre指向鏈表最後一個結點
pPre=pNode;
}
pNode=pNode->right;
}
pPre->right=NULL;
return pRootOfTree;
}
};
畫個圖,手動走一邊流程