二叉樹的遞歸很簡單,但是非遞歸就有點復雜了。
第一種先序遍歷、中序遍歷、第一種后序遍歷都是一直將左子樹壓入棧,其中先序遍歷和中序遍歷輸出位置不同,后序遍歷則需要前驅標記pre來判斷右孩子是否訪問過;
第二種先序遍歷和第二種后序遍歷是根據層序遍歷的思想寫的,將隊列換成棧,順序換成先入右孩子再入左孩子,但是后序遍歷需要用pre判斷左右孩子是否都訪問過。
測試數據:AB#DF##G##CEH##I###
#include <bits/stdc++.h> using namespace std; struct node { char data; node *l, *r; }; //建立二叉樹 void creat(node *&t) { char c; cin>>c; if(c == '#') { t = NULL; return; } t = (node*)malloc(sizeof(node)); t->data = c; creat(t->l); creat(t->r); } //先序遍歷二叉樹(遞歸) void pre_di(node *t) { if(!t) return; printf("%c ", t->data); pre_di(t->l); pre_di(t->r); } //中序遍歷二叉樹(遞歸) void in_di(node *t) { if(!t) return; in_di(t->l); printf("%c ", t->data); in_di(t->r); } //后序遍歷二叉樹(遞歸) void post_di(node *t) { if(!t) return; post_di(t->l); post_di(t->r); printf("%c ", t->data); } //先序遍歷二叉樹(非遞歸1) void pre_no_di1(node *t) { stack<node*>S; while(t || !S.empty()) { if(t) { printf("%c ", t->data); S.push(t); t = t->l; } else { t= S.top(); S.pop(); t = t->r; } } cout<<endl; } //先序遍歷二叉樹(非遞歸2) void pre_no_di2(node *t) { stack<node*>S; S.push(t); while(!S.empty()) { t = S.top(); S.pop(); printf("%c ", t->data); if(t->r) S.push(t->r); if(t->l) S.push(t->l); } cout<<endl; } //中序遍歷二叉樹(非遞歸) void in_no_di(node *t) { stack<node*>S; while(t || !S.empty()) { if(t) { S.push(t); t = t->l; } else { t = S.top(); S.pop(); printf("%c ", t->data); t = t->r; } } cout<<endl; } //后序遍歷二叉樹(非遞歸1) void post_no_di1(node *t) { stack<node*>S; node *pre = NULL; while(t || !S.empty()) { while(t) { S.push(t); t = t->l; } t = S.top(); if(!t->r || pre == t->r) { printf("%c ", t->data); pre = t; S.pop(); t = NULL; } else t = t->r; } cout<<endl; } //后序遍歷二叉樹(非遞歸2) void post_no_di2(node *t) { stack<node*>S; node *pre = NULL;//pre本來想寫char類型,但是下面if里就要換成pre==t->l->data,如果t->l為空則會報錯! S.push(t); while(!S.empty()) { t = S.top(); if((t->l == NULL && t->r == NULL) || (pre != NULL && (pre == t->l || pre == t->r))) //pre=t->l代表僅有左且已訪問或者先訪問過右又訪問了左 { printf("%c ", t->data); pre = t; S.pop(); } else { if(t->r) S.push(t->r); if(t->l) S.push(t->l); } } cout<<endl; } //層序遍歷 void ceng(node *t) { queue<node*>Q; Q.push(t); while(!Q.empty()) { t = Q.front(); Q.pop(); printf("%c ", t->data); if(t->l) Q.push(t->l); if(t->r) Q.push(t->r); } cout<<endl; } //銷毀二叉樹 void Free(node *&t) { if(t->l) Free(t->l); if(t->r) Free(t->r); free(t); } int main() { node *t; puts("請輸入二叉樹"); creat(t); puts("創建成功"); printf("先序遍歷二叉樹(遞歸): "); pre_di(t); cout<<endl; printf("先序遍歷二叉樹(非遞歸1):"); pre_no_di1(t); printf("先序遍歷二叉樹(非遞歸2):"); pre_no_di2(t); printf("\n中序遍歷二叉樹(遞歸): "); in_di(t); cout<<endl; printf("中序遍歷二叉樹(非遞歸): "); in_no_di(t); printf("\n后序遍歷二叉樹(遞歸): "); post_di(t); cout<<endl; printf("后序遍歷二叉樹(非遞歸1):"); post_no_di1(t); printf("后序遍歷二叉樹(非遞歸2):"); post_no_di2(t); printf("\n層序遍歷二叉樹:"); ceng(t); Free(t); return 0; }
運行截圖: