只有先序遍歷部分的源代碼:https://github.com/cr19941016/preOrderTree
實現環境:ubuntu16.04 + cmake3.5.1
先序遍歷遞歸的本質就是循環和棧
void TreeHandler::myPreOrder(TreeNode* root){ // 非遞歸先序遍歷二叉樹git
cout << "mypre: ";
if(!root)
return;
stack<TreeNode*> stk;
stk.push(root);
while(!stk.empty()){
TreeNode* p = stk.top();
cout << p->data << " ";
stk.pop();
if(p->rightchild){
stk.push(p->rightchild);
}
if(p->leftchild){
stk.push(p->leftchild);
}
}
cout << endl;
}
中序遍歷:
void TreeHandler::myMidOrder(TreeNode* root){
cout << "mymid: ";
stack<TreeNode*> stk;
TreeNode* p = root;
while(p || !stk.empty()){
while(p){
stk.push(p);
p = p->leftchild;
}
if(!stk.empty()){
p = stk.top();
stk.pop();
cout << p->data << ' ';
p = p->rightchild;
}
}
cout << endl;
}
後序遍歷(比較麻煩,另一種解法是採用一個指針保存上次遍歷的節點,避免重複遍歷),使用兩個棧,一個負責按照“根、右、左”的順序入棧出棧,另一個負責逆序記錄輸出的數據:
void TreeHandler::myPostOrder(TreeNode* root){
cout << "mypost: ";
if(!root){
return;
}
stack<TreeNode*> stk1; // 輔助棧
stack<TreeNode*> stk2; // 逆序記錄遍歷的數據
TreeNode* p = root;
while(p || !stk1.empty()){
if(p){
stk2.push(p);
stk1.push(p);
p = p->rightchild;
}
else{
p = stk1.top();
stk1.pop();
p = p->leftchild;
}
}
while(!stk2.empty()){
p = stk2.top();
stk2.pop();
cout << p->data << ' ';
}
cout << endl;
}
其他:使用隊列將數組轉化爲生成二叉樹
#include "preodertree.h"
TreeNode* TreeHandler::createTree(vector<int> &nums){ // 根據數組生成二叉樹,如果數值爲-1則表示空位
TreeNode* root = NULL;
if(nums.empty()){
return root;
}
root = new TreeNode(nums[0]);
queue<TreeNode*> q;
q.push(root);
for(unsigned int i = 1; i < nums.size(); ){
TreeNode* p = q.front();
if(nums[i] != -1){
TreeNode* l = new TreeNode(nums[i]);
p->leftchild = l;
q.push(l);
i++;
}
else i++;
if(i < nums.size() && nums[i] != -1){
TreeNode* r = new TreeNode(nums[i]);
p->rightchild = r;
q.push(r);
i++;
}
else i++;
q.pop();
}
return root;
}
此外,不使用棧,空間複雜度爲O(1),時間複雜度爲O(n)的Morris Traversal算法:
https://www.jianshu.com/p/d2059062efac