一、前序非遞歸遍歷
1、算法思路
利用棧先進後出的特性,在一個有三個結點的子樹中,先對根節點做出操作,再將右子樹結點入棧,再將左子樹結點入棧,這樣利用棧遍歷的順序就是根----左-----右(因爲根已經最先處理)。
思路比較簡單,直接看源碼即可理解。
2、源碼
void Pre_Travel(TreeNode* root)
{
stack<TreeNode*> stackTree;
if (root == NULL) return;
stackTree.push(root);
while (stackTree.size() > 0)
{
TreeNode* tempNode = stackTree.top();
stackTree.pop();
printf("%d ", tempNode->val);
if (tempNode->right != NULL)
stackTree.push(tempNode->right);
if (tempNode->left != NULL)
stackTree.push(tempNode->left);
}
}
二、中序遍歷
1、算法思路
最重要的第一步就是,先找到左子樹中最後一個沒有左子節點的結點。
剩下內容比較簡單 ,容易理解,看源碼即可。
2、源碼
void Mid_Travel(TreeNode* root)
{
if (root == NULL)
return;
stack<TreeNode*> stackTree;
TreeNode* p = root;
while (p || stackTree.size() > 0)
{
//到最後一個沒有左子樹的結點
while (p)
{
stackTree.push(p);
p = p->left;
}
if (stackTree.size() > 0)
{
TreeNode* tempNode = stackTree.top();
stackTree.pop();
printf("%d ", tempNode->val);
//對右子樹繼續進行遍歷其左子樹
p = tempNode->right;
}
}
}
三、後序遍歷
1、算法思路
三種非遞歸算法中,後序遍歷算是相對更加複雜一點,複雜的原因在於,對於根節點的訪問只有在子節點都被訪問之後才能進行,這就需要使用一個緩存,來記錄上次訪問的結點,再將當前訪問結點的左右子樹和緩存比較,如果相等,說明其左右子樹已經被訪問過,此時可以讀取當前節點,反之不行。
2、源碼
void Pos_Travel(TreeNode* root)
{
if (root == NULL)
return;
stack<TreeNode*> stackTree;
TreeNode* pre = NULL;
stackTree.push(root);
while (stackTree.size() > 0)
{
TreeNode* tempNode = stackTree.top();
//如果左右子樹被訪問過
if ((tempNode->left == NULL && tempNode->right == NULL) || ((pre != NULL) && (pre == tempNode->left || pre == tempNode->right)))
{
printf("%d ", tempNode->val);
pre = tempNode;
stackTree.pop();
}
//左右子樹沒有被訪問過
else
{
if (tempNode->right != NULL)
stackTree.push(tempNode->right);
if (tempNode->left != NULL)
stackTree.push(tempNode->left);
}
}
}
四、完整Demo
#include <vector>
#include <stack>
using namespace std;
struct TreeNode
{
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int v) :val(v), left(NULL), right(NULL) {};
};
class Solution
{
public:
void Pre_Travel(TreeNode* root)
{
stack<TreeNode*> stackTree;
if (root == NULL) return;
stackTree.push(root);
while (stackTree.size() > 0)
{
TreeNode* tempNode = stackTree.top();
stackTree.pop();
printf("%d ", tempNode->val);
if (tempNode->right != NULL)
stackTree.push(tempNode->right);
if (tempNode->left != NULL)
stackTree.push(tempNode->left);
}
}
void Mid_Travel(TreeNode* root)
{
if (root == NULL)
return;
stack<TreeNode*> stackTree;
TreeNode* p = root;
while (p || stackTree.size() > 0)
{
//到最後一個沒有左子樹的結點
while (p)
{
stackTree.push(p);
p = p->left;
}
if (stackTree.size() > 0)
{
TreeNode* tempNode = stackTree.top();
stackTree.pop();
printf("%d ", tempNode->val);
//對右子樹繼續進行遍歷其左子樹
p = tempNode->right;
}
}
}
void Pos_Travel(TreeNode* root)
{
if (root == NULL)
return;
stack<TreeNode*> stackTree;
TreeNode* pre = NULL;
stackTree.push(root);
while (stackTree.size() > 0)
{
TreeNode* tempNode = stackTree.top();
//如果左右子樹被訪問過
if ((tempNode->left == NULL && tempNode->right == NULL) || ((pre != NULL) && (pre == tempNode->left || pre == tempNode->right)))
{
printf("%d ", tempNode->val);
pre = tempNode;
stackTree.pop();
}
//左右子樹沒有被訪問過
else
{
if (tempNode->right != NULL)
stackTree.push(tempNode->right);
if (tempNode->left != NULL)
stackTree.push(tempNode->left);
}
}
}
};
void main()
{
TreeNode* root=new TreeNode(3);
root->left = new TreeNode(2);
root->right = new TreeNode(5);
root->left->left = new TreeNode(4);
root->left->right = new TreeNode(7);
Solution solution;
solution.Mid_Travel(root);
}