資料結構——二叉樹的遞迴與非遞迴遍歷(先序,中序,後序)
阿新 • • 發佈:2018-12-25
實驗專案五 二叉樹基本操作的實現
課程名稱:資料結構
實驗專案名稱:二叉樹基本操作的實現
實驗目的:
- 1.掌握樹的基本操作—遍歷。
實驗要求:
- 1、 分別用遞迴和非遞迴的方法實現一棵樹的三種遍歷。
實驗過程:
- 建立一棵二叉樹(二叉樹如下圖所示);
- 用遞迴演算法實現對該樹的三種遍歷;
- 用非遞迴演算法實現對該樹的三種遍歷;
- 輸入選項:0或1,0為遞迴遍歷,1為非遞迴遍歷。
- 根據輸入的選項,分別呼叫遞迴或非遞迴演算法輸出先序、中序、後序遍歷序列。
實驗報告中給出先序和後序遍歷的非遞迴實現演算法程式碼。
實驗結果:
- 輸入:ABD##E##CF#G###(建立二叉樹)
- 輸入:0(遞迴演算法)
- 輸出:先序遍歷:ABDECFG
中序遍歷:DBEAFGC
後序遍歷:DEBGFCA - 輸入:1(非遞迴實現)
- 輸出:先序遍歷: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;
}