1. 程式人生 > >資料結構——二叉樹的遞迴與非遞迴遍歷(先序,中序,後序)

資料結構——二叉樹的遞迴與非遞迴遍歷(先序,中序,後序)

實驗專案五 二叉樹基本操作的實現

課程名稱:資料結構

實驗專案名稱:二叉樹基本操作的實現

實驗目的:

  • 1.掌握樹的基本操作—遍歷。

實驗要求:

  • 1、 分別用遞迴和非遞迴的方法實現一棵樹的三種遍歷。

實驗過程:

  1. 建立一棵二叉樹(二叉樹如下圖所示);
  2. 用遞迴演算法實現對該樹的三種遍歷;
  3. 用非遞迴演算法實現對該樹的三種遍歷;
  4. 輸入選項:0或1,0為遞迴遍歷,1為非遞迴遍歷。
  5. 根據輸入的選項,分別呼叫遞迴或非遞迴演算法輸出先序、中序、後序遍歷序列。

實驗報告中給出先序和後序遍歷的非遞迴實現演算法程式碼。

實驗結果:

  1. 輸入:ABD##E##CF#G###(建立二叉樹)
  2. 輸入:0(遞迴演算法)
  3. 輸出:先序遍歷:ABDECFG
    中序遍歷:DBEAFGC
    後序遍歷:DEBGFCA
  4. 輸入:1(非遞迴實現)
  5. 輸出:先序遍歷:ABDECFG
    中序遍歷:DBEAFGC
    後序遍歷:DEBGFCA

程式碼:

#include<bits/stdc++.h>
using namespace std;
#define TElemType char
typedef int Status;
#define OK 1
#define ERROR 0
char ch;
const int MAXSIZE = 110;

typedef struct BiTNode {
    TElemType data;
struct BiTNode *lchild, *rchild; }BiTNode, *BiTree; BiTNode *T; BiTree q, p; typedef BiTree SElemType; typedef struct{//定義順序棧 SElemType *base; SElemType *top; int stacksize; }SqStack; SqStack S; Status InitStack(SqStack &S){ S.base = new SElemType[MAXSIZE]; if(!S.base)
exit(OVERFLOW); S.top = S.base; S.stacksize = MAXSIZE; return OK; } Status Push(SqStack &S, SElemType e)//入棧 { if(S.top - S.base == S.stacksize) //判斷棧滿 return ERROR; *S.top++ = e; //元素e壓入棧頂,棧頂指標上移一位; return OK; } Status Pop(SqStack &S, SElemType &e){//出棧 if(S.top == S.base) return ERROR; e = *--S.top; return OK; } SElemType GetTop(SqStack S){//取棧頂元素 if(S.top != S.base) return *(S.top - 1); } Status StackEmpty(SqStack &S){ if(S.top - S.base == 0) return OK; else return ERROR; } void CreatBiTree(BiTree &T){//建樹 cin >> ch;//讀入字元 if(ch == '#') T = NULL;//如果字元為'#',說明已經到了葉結點 else{//遞迴 T = new BiTNode; T->data = ch; CreatBiTree(T->lchild); CreatBiTree(T->rchild); } } void DgXx(BiTree T){//遞迴先序 if(T){ cout << T->data; DgXx(T->lchild); DgXx(T->rchild); } } void DgZx(BiTree T){//遞迴中序 if(T){ DgZx(T->lchild); cout << T->data; DgZx(T->rchild); } } void DgHx(BiTree T){//遞迴後序 if(T){ DgHx(T->lchild); DgHx(T->rchild); cout << T->data; } } void InRrderTraverse0(BiTree T){//非遞迴先序 InitStack(S);//初始化棧S p = T; while(p || !StackEmpty(S)) {//如果樹不為空或者棧不為空 if(p){ Push(S, p) ;//將結點入棧 cout << p->data;//輸出根結點的值 p = p->lchild ;//把左孩子作為根節點 } else{//如果樹空,說明左樹已經遍歷完成 Pop(S, p) ;//彈出結點 p = p->rchild ;//開始遍歷右樹 } } } void InRrderTraverse1(BiTree T){//非遞迴中序遍歷 InitStack(S);//初始化棧 p = T; q = new BiTNode; while(p || !StackEmpty(S)){ if(p){//p非空 Push(S, p);//根指標進棧 p = p->lchild;//根指標進棧,遍歷左子樹 } else{//p為空 Pop(S, q);//退棧 cout << q->data;//訪問根結點 p = q->rchild;//遍歷右子樹 } } } void InRrderTraverse2(BiTree T){//非遞迴後序遍歷 InitStack(S); Push(S, T);//把根節點進棧 BiTNode *pre, *cur; cur = NULL;//當前結點 pre = NULL;//上一結點 while(!StackEmpty(S)){//棧非空 cur = GetTop(S);//把根節點給當前結點 if((cur->lchild == NULL && cur->rchild == NULL) || (pre != NULL && (pre == cur->lchild || pre == cur->rchild))) {//如果左右子樹都沒有或者左右子樹都已經訪問過了 cout << cur->data;//直接輸出根結點 Pop(S, cur);//將此時的根節點彈出 pre = cur;//更新pre } else{//記得先進右子樹後進左子樹,這樣輸出的順序才對。 if(cur->rchild != NULL){//如果右子樹不為空 Push(S, cur->rchild) ;//把右子樹進棧 } if(cur->lchild != NULL){//如果左子樹不為空 Push(S, cur->lchild) ;//把左子樹進棧 } } } } int main(){ CreatBiTree(T); int temp; printf("請輸入遍歷二叉樹的方法,0:遞迴遍歷,1:遞迴遍歷,其他數字:結束詢問\n"); while(scanf("%d",&temp) != EOF){ if(temp == 0){ cout << "先序遍歷:\n"; DgXx(T); cout << endl; cout << "中序遍歷:\n"; DgZx(T); cout << endl; cout << "後序遍歷:\n"; DgHx(T); cout << endl; } else if(temp == 1){ cout << "先序遍歷:\n"; InRrderTraverse0(T); cout << endl; cout << "中序遍歷:\n"; InRrderTraverse1(T); cout << endl; cout << "後序遍歷:\n"; InRrderTraverse2(T); cout << endl; } else break; printf("請輸入遍歷二叉樹的方法,0:遞迴遍歷,1:遞迴遍歷,其他數字:結束詢問\n"); } printf("感謝使用\n"); return 0; }