- 從先序遍歷還原二叉樹
我們從二叉樹的根節點 root 開始進行深度優先搜索。
在遍歷中的每個節點處,我們輸出 D 條短劃線(其中 D 是該節點的深度),然後輸出該節點的值。(如果節點的深度爲 D,則其直接子節點的深度爲 D + 1。根節點的深度爲 0)。
如果節點只有一個子節點,那麼保證該子節點爲左子節點。
給出遍歷輸出 S,還原樹並返回其根節點 root。
思路:
因爲給出的是先序遍歷的二叉樹,按照這個順序重建二叉樹,就需要將每個子樹的根節點記錄下來。
這裏使用了一個棧來保存根節點的指針和深度。新節點加入二叉樹中,需要從棧找到父節點,根據深度進行判斷(深度相差1),就是一個單調棧,深度總是增加的。
TreeNode* recoverFromPreorder(string S) {
//構造樹,需要記錄每層的節點,
S+='-'; //爲了將最後一個數加入樹中,不用多做處理
TreeNode* root;
int i = 0;
int num = 0;
while(i < S.size())
{
if(S[i]!='-')
{
num = num*10 + S[i]-'0';
}
else
{
break;
}
i++;
}
root = new TreeNode(num);
bool flag = false; //false 記錄-, true 記錄數字
int count = 0; //記錄長度-
stack<pair<TreeNode*, int>> rec;
rec.push(pair<TreeNode*,int>(root, 0));
while(i < S.size())
{
if(flag)
{
if(S[i]=='-')
{
flag = false;
//新節點
TreeNode* node = new TreeNode(num);
pair<TreeNode*, int> pre = rec.top();
while(pre.second+1!= count)
{
rec.pop();
pre = rec.top();
}
if(pre.second + 1 == count)
{
if(pre.first->left)
{
pre.first->right = node;
rec.push(pair<TreeNode*,int>(node, count));
}
else
{
pre.first->left = node;
rec.push(pair<TreeNode*,int>(node, count));
}
}
count=0;
i--;
}
else
{
num = num*10 + S[i]-'0';
}
}
else
{
if(S[i]!='-')
{
flag = true;
num = 0;
i--;
}
else
{
count++;
}
}
i++;
}
return root;
}