上篇樹(二叉樹)的創建和遍歷算法(一)對二叉樹的遍歷是遞歸的方法,這裏利用非遞歸的方法實現二叉樹的遍歷。首先要看懂上篇樹(二叉樹)的創建和遍歷算法(一)。html
關於二叉樹的創建就不具體講了。看上篇就OK了,那就直接見代碼,非遞歸的方法實現對其的遍歷。ios
//非遞歸方式前序遍歷 /* 思路:將T入棧,遍歷左子樹;遍歷完左子樹返回時,棧頂元素應爲T,出棧,再先序遍歷T的右子樹。*/ void PreOrder(BiTree T){ stack<BiTree> stack; //p是遍歷指針 BiTree p = T; //p不爲空或者棧不空時循環 while (p || !stack.empty()) { if (p != NULL) { //存入棧中 stack.push(p); //對樹中的結點進行操做 operation1(p->data); //遍歷左子樹 p = p->lchild; } else { //退棧 p = stack.top(); stack.pop(); //訪問右子樹 p = p->rchild; } } } //非遞歸中序遍歷 void InOrder(BiTree T) { stack<BiTree> stack; //p是遍歷指針 BiTree p = T; //p不爲空或者棧不空時循環 while (p || !stack.empty()) { if (p != NULL) { //存入棧中 stack.push(p); //遍歷左子樹 p = p->lchild; } else { //退棧 p = stack.top(); operation1(p->data); //對樹中的結點進行操做 stack.pop(); //訪問右子樹 p = p->rchild; } } } //非遞歸後序遍歷 typedef struct BiTNodePost{ BiTree biTree; char tag; }BiTNodePost, *BiTreePost; void PostOrder(BiTree T) { stack<BiTreePost> stack; //p是遍歷指針 BiTree p = T; BiTreePost BT; //棧不空或者p不空時循環 while (p != NULL || !stack.empty()) { //遍歷左子樹 while (p != NULL) { BT = (BiTreePost)malloc(sizeof(BiTNodePost)); BT->biTree = p; //訪問過左子樹 BT->tag = 'L'; stack.push(BT); p = p->lchild; } //左右子樹訪問完畢訪問根節點 while (!stack.empty() && (stack.top())->tag == 'R') { BT = stack.top(); //退棧 stack.pop(); BT->biTree; cout<<BT->biTree->data<<" "; } //遍歷右子樹 if (!stack.empty()) { BT = stack.top(); //訪問過右子樹 BT->tag = 'R'; p = BT->biTree; p = p->rchild; } } } //層次遍歷 void LevelOrder(BiTree T) { BiTree p = T; queue<BiTree> queue; //根節點入隊 queue.push(p); //隊列不空循環 while (!queue.empty()) { //對頭元素出隊 p = queue.front(); //訪問p指向的結點 operation1(p->data); //退出隊列 queue.pop(); //左孩子不爲空,將左孩子入隊 if (p->lchild != NULL) { queue.push(p->lchild); } //右孩子不空,將右孩子入隊 if (p->rchild != NULL) { queue.push(p->rchild); } } }
1.完整的代碼:算法
#include<iostream> #include<stdlib.h> #include<stack> #include<queue> using namespace std; typedef char ElemType; //二叉樹的二叉鏈表結構,也就是二叉樹的存儲結構,1個數據域,2個指針域(分別指向左右孩子) typedef struct BiTNode { ElemType data; struct BiTNode *lchild, *rchild; }BiTNode, *BiTree; //二叉樹的創建,按前序遍歷的方式創建二叉樹,固然也能夠以中序或後序的方式創建二叉樹 void CreateBiTree(BiTree *T) { ElemType ch; cin >> ch; if (ch == '#') *T = NULL; //保證是葉結點 else { *T = (BiTree)malloc(sizeof(BiTNode)); //if (!*T) //exit(OVERFLOW); //內存分配失敗則退出。 (*T)->data = ch;//生成結點 CreateBiTree(&(*T)->lchild);//構造左子樹 CreateBiTree(&(*T)->rchild);//構造右子樹 } } //表示對遍歷到的結點數據進行的處理操做,此處操做是將樹結點前序遍歷輸出 void operation1(ElemType ch) { cout << ch << " "; } //此處在輸出的基礎上,並輸出層數 void operation2(ElemType ch, int level) { cout << ch << "在第" << level << "層" << " "; } //遞歸方式前序遍歷二叉樹 void PreOrderTraverse(BiTree T, int level) { if (T == NULL) return; /*此處表示對遍歷的樹結點進行的操做,根據你本身的要求進行操做,這裏只是輸出告終點的數據*/ operation1(T->data); //operation2(T->data, level); //輸出了層數 PreOrderTraverse(T->lchild, level + 1); PreOrderTraverse(T->rchild, level + 1); } //遞歸方式中序遍歷二叉樹 void InOrderTraverse(BiTree T,int level) { if(T==NULL) return; InOrderTraverse(T->lchild,level+1); operation1(T->data); //operation2(T->data, level); //輸出了層數 InOrderTraverse(T->rchild,level+1); } //遞歸方式後序遍歷二叉樹 void PostOrderTraverse(BiTree T,int level) { if(T==NULL) return; PostOrderTraverse(T->lchild,level+1); PostOrderTraverse(T->rchild,level+1); operation1(T->data); //operation2(T->data, level); //輸出了層數 } //非遞歸方式前序遍歷 /* 思路:將T入棧,遍歷左子樹;遍歷完左子樹返回時,棧頂元素應爲T,出棧,再先序遍歷T的右子樹。*/ void PreOrder(BiTree T){ stack<BiTree> stack; //p是遍歷指針 BiTree p = T; //p不爲空或者棧不空時循環 while (p || !stack.empty()) { if (p != NULL) { //存入棧中 stack.push(p); //對樹中的結點進行操做 operation1(p->data); //遍歷左子樹 p = p->lchild; } else { //退棧 p = stack.top(); stack.pop(); //訪問右子樹 p = p->rchild; } } } //非遞歸中序遍歷 void InOrder(BiTree T) { stack<BiTree> stack; //p是遍歷指針 BiTree p = T; //p不爲空或者棧不空時循環 while (p || !stack.empty()) { if (p != NULL) { //存入棧中 stack.push(p); //遍歷左子樹 p = p->lchild; } else { //退棧 p = stack.top(); operation1(p->data); //對樹中的結點進行操做 stack.pop(); //訪問右子樹 p = p->rchild; } } } //非遞歸後序遍歷 typedef struct BiTNodePost{ BiTree biTree; char tag; }BiTNodePost, *BiTreePost; void PostOrder(BiTree T) { stack<BiTreePost> stack; //p是遍歷指針 BiTree p = T; BiTreePost BT; //棧不空或者p不空時循環 while (p != NULL || !stack.empty()) { //遍歷左子樹 while (p != NULL) { BT = (BiTreePost)malloc(sizeof(BiTNodePost)); BT->biTree = p; //訪問過左子樹 BT->tag = 'L'; stack.push(BT); p = p->lchild; } //左右子樹訪問完畢訪問根節點 while (!stack.empty() && (stack.top())->tag == 'R') { BT = stack.top(); //退棧 stack.pop(); BT->biTree; cout<<BT->biTree->data<<" "; } //遍歷右子樹 if (!stack.empty()) { BT = stack.top(); //訪問過右子樹 BT->tag = 'R'; p = BT->biTree; p = p->rchild; } } } //層次遍歷 void LevelOrder(BiTree T) { BiTree p = T; queue<BiTree> queue; //根節點入隊 queue.push(p); //隊列不空循環 while (!queue.empty()) { //對頭元素出隊 p = queue.front(); //訪問p指向的結點 operation1(p->data); //退出隊列 queue.pop(); //左孩子不爲空,將左孩子入隊 if (p->lchild != NULL) { queue.push(p->lchild); } //右孩子不空,將右孩子入隊 if (p->rchild != NULL) { queue.push(p->rchild); } } } int main() { int level = 1; //表層數 BiTree T = NULL; cout << "請之前序遍歷的方式輸入擴展二叉樹:"; //相似輸入AB#D##C## CreateBiTree(&T);// 創建二叉樹,沒有樹,怎麼遍歷 cout << "遞歸前序遍歷輸出爲:" << endl; PreOrderTraverse(T, level);//進行前序遍歷,其中operation1()和operation2()函數表示對遍歷的結點數據進行的處理操做 cout << endl; cout << "遞歸中序遍歷輸出爲:" << endl; InOrderTraverse(T, level); cout << endl; cout << "遞歸後序遍歷輸出爲:" << endl; PostOrderTraverse(T, level); cout << endl; cout<<"非遞歸前序遍歷輸出爲:"<<endl; PreOrder(T); cout<<endl; cout<<"非遞歸前序遍歷輸出爲:"<<endl; InOrder(T); cout<<endl; cout<<"非遞歸前序遍歷輸出爲:"<<endl; PostOrder(T); cout<<endl; cout<<"層序遍歷輸出爲:"<<endl; LevelOrder(T); cout<<endl; return 0; }
2. 運行結果:函數