中序遍歷
一直遍歷左子樹到空,然後轉移到右子樹
void inorder(TreeNode *root,vector<int> &path){
stack<TreeNode*> s;
TreeNode* p=root;
while(p||!s.empty()){ //節點不爲空時,或者棧不爲空的情況下繼續執行循環體
//一直遍歷左子樹直到底
while(p!=NULL){
s.push(p);
p=p->left;
}
//p爲空,說明已經到了左子樹的最下面,這時需要出棧
if(!s.empty()){
p=s.top();
path.push_back(p->val);
s.pop();
//進入右子樹,開始新一輪的左子樹遍歷(遞歸的自我實現)
p=p->right;
}
}
}
先序遍歷
先序遍歷和中序遍歷差不多,也是需要藉助根節點訪問右子樹,只不過和中序遍歷的區別在於在根節點被壓棧時就輸出它的值,而不是在出棧的時候再訪問
void preOrder(TreeNode* root,vector<int> &path){
if(root==NULL) return;
stack<TreeNode*> s;
TreeNode* p=root;
while(!s.empty()||p!=NULL){
while(p){
path.push_back(p->val);
s.push(p);
p=p->left;
}
if(!s.empty()){
TreeNode* temp=s.top();
s.pop();
p=temp->right;
}
}
}
後序遍歷
需要判斷上次訪問的是位於左子樹還是右子樹。若位於左子樹,則要跳過根節點,先進入右子樹,再訪問根節點;若是位於右子樹,則直接訪問根節點。
需要保存當前訪問節點和上次訪問節點
後序遍歷訪問的一直都是從棧中彈出的元素
- 使用棧來實現,並設置兩個指針,分別指向當前訪問的節點和上次訪問的節點
- 初始化時將當前訪問的節點指向最左下的節點,上次訪問的節點爲NULL
- 取棧頂元素爲當前訪問節點,如果此節點沒有右孩子或者是右孩子爲上次訪問節點,那麼輸出此節點信息,並將此節點賦值給上次訪問節點,繼續從棧中取元素
- 如果右孩子不是上面說的那種情況的話,將當前訪問節點(也就是原來的棧頂元素)再次壓入棧中,然後訪問右子樹,將右子樹的左節點左節點持續壓入棧中,繼續循環第3步
void postOrder(TreeNode* root,vector<int> &path){
if(root==NULL) return;
stack<TreeNode*> s;
//當前訪問節點,上次訪問節點
TreeNode *pCur,*pLastVisit;
pCur=root;
pListVisit=NULL;
//從左子樹的最下邊開始訪問
while(pCur){
s.push(pCur);
pCur=pCur->left;
}
while(!s.empty()){
//走到這裏時,已經遍歷到二叉樹的最低端
pCur=s.top();
s.pop();
//如果沒有右子樹或者右子樹已經被訪問,那麼訪問這個根節點
if(pCur->right==NULL||pCur->right==pLastVisit){
path.push_back(pCur->val);
//修改爲最近被訪問的節點
//只有輸出結果的時候纔會修改上次訪問節點
pLastVisit=pCur;
}
else{
//將根節點再次入棧
s.push(pCur);
//訪問右子樹,進入右子樹
pCur=pCur->right;
while(pCur){
s.push(pCur);
pCur=pCur->left;
}
}
}
}
層序遍歷
層序遍歷用非遞歸的方法更容易實現些,使用隊列保存節點,然後逐層遍歷即可
用遞歸實現的方法並不常用,首先要知道樹的深度,逐層輸出(這裏的遞歸的作用似乎就只是到達了對應的層)
void level(TreeNode* root,int i,vector<int>& path){
if(root==NULL||i==0) return;
if(i==1){
path.push_back(root->val);
}
level(root->left,i-1,path);
level(root->right,i-1,path);
}
int getDepth(TreeNode *root,int depth){
if(root==NULL)
return depth;
else{
int l=getDepth(root->left,depth+1);
int r=getDepth(root->right,depth+1);
return max(l,r);
}
}
void levelOrder(TreeNode* root,vector<int>& path){
if(root==NULL) return;
int dep=getDepth(root);
for(int i=1;i<=dep;i++){
level(root,i,path);
}
}
測試代碼
int main(){
TreeNode* one=new TreeNode();
one->val=1;
TreeNode* two=new TreeNode();
two->val=2;
TreeNode* three=new TreeNode();
three->val=3;
TreeNode* four=new TreeNode();
four->val=4;
one->right=two;
one->left=three;
three->left=four;
vector<int> path;
// levelOrder(one,path);
// inorder(one,path);
// preOrder(one,path);
postOrder(one,path);
for(int i=0;i<path.size();i++){
cout<<path[i]<<" ";
}
return 0;
}