建立二叉樹,實現二叉樹的先序遍歷、中序和後序遍歷的非遞迴演算法
阿新 • • 發佈:2019-02-18
先序遍歷:若二叉樹為空,則空操作;否則訪問根節點;先序遍歷左子樹;先序遍歷右子樹。
中序遍歷:若二叉樹為空,則空操作;否則中序遍歷左子樹;訪問根節點;中序遍歷右子樹。
後序遍歷:若二叉樹為空,則空操作;否則後序遍歷左子樹;後序遍歷右子樹;訪問根節點。
/*
* Created by Microsoft Visual Studio 2013
* @author: Teresa
* @date: 2017-10-22
* @description: 二叉樹遍歷 非遞迴
*/
#include <stdio.h>
#include <stdlib.h>
/*函式狀態碼*/
#define TRUE 1 //成功
#define OK 1
#define FALSE 0 //失敗
#define ERROR 0 //錯誤
#define INFEASIBLE -1 //不可行的
#define OVERFLOW -2 //溢位
typedef int Status; //函式的返回值型別
//二叉樹的二叉連結串列儲存表示
typedef char TElemType;
typedef struct BiNode{
TElemType data;
struct BiNode *lchild, *rchild;
} BiNode , *BiTree;
//棧的順序儲存結構
#define STACK_INIT_SIZE 100 //儲存空間初始分配量
#define STACKINCREMENT 10 //儲存空間分配增量
typedef struct{
BiTree *base;
BiTree *top;
int stacksize;
} Stack;
//初始化棧
Status InitStack(Stack *s){
s->base = (BiTree*)malloc(sizeof(BiTree)*STACK_INIT_SIZE);
s->top = s->base;
s->stacksize = STACK_INIT_SIZE;
return OK;
}
//判斷棧是否為空
Status StackEmpty(Stack *s){
if (s->base == s->top)
return OK;
return ERROR;
}
//獲得棧頂元素
Status GetTop(Stack *s, BiTree *c){
if (StackEmpty(s))
return ERROR;
*c = *(s->top - 1);
return OK;
}
//進棧
Status Push(Stack *s, BiTree c)
{
//如果空間不夠,增加空間的分配
if (s->top - s->base >= s->stacksize){
s->base = (BiTree*)realloc(s->base, sizeof(BiTree)*(s->stacksize + STACKINCREMENT));
s->stacksize = s->stacksize + STACKINCREMENT;
}
*(s->top++) = c;
return OK;
}
//出棧
Status Pop(Stack *s, BiTree *c){
if (StackEmpty(s))
return ERROR;
*c = *(--s->top);
return OK;
}
//遍歷資料元素時所呼叫函式
Status PrintElement(TElemType e){
putchar(e);
return OK;
}
//按先序次序輸入二叉樹中結點的值(一個字元),空格字元表示空樹,構造二叉連結串列表示的二叉樹T。
Status CreatBiTree(BiTree *T){
char ch;
scanf("%c", &ch);
//如果當前輸入的字元為空格,則(*T)指向空樹。
if (ch == ' '){
(*T) = NULL;
}
else{
if (!((*T) = (BiTree)malloc(sizeof(BiNode))))
exit(OVERFLOW);
(*T)->data = ch; //生成根結點
CreatBiTree(&((*T)->lchild)); //構造左子樹
CreatBiTree(&((*T)->rchild)); //構造右子樹
}
return OK;
}
//先序遍歷二叉樹,非遞迴演算法。
Status PreOrderTraverse_NonRecursive(BiTree T, Status(*Visit)(TElemType e)){
Stack *S; //棧S中儲存指向樹結點的指標。
BiTree p;
S = (Stack*)malloc(sizeof(Stack));
InitStack(S);
Push(S, T); //根指標進棧。
while (!StackEmpty(S)){
//獲取棧頂指標,如果棧頂指標不為空,訪問該結點。並將該結點的左子樹進棧。
if (GetTop(S, &p) && p){
if (!Visit(p->data))
return ERROR;
Push(S, p->lchild);
}
//棧頂指標為空,表明之前壓入的左子樹或者右子樹為空。
else{
Pop(S, &p); //空指標退棧
if (!StackEmpty(S)){
Pop(S, &p); //已被訪問過的根結點退棧。此時,該退棧結點的左子樹已被全部訪問過。
Push(S, p->rchild); //右子樹進棧。
}
}
}
return OK;
}
//採用二叉連結串列儲存結構,Visit是對資料元素進行操作的應用函式,
//中序遍歷二叉樹的非遞迴演算法,對每個資料元素呼叫函式Visit。
Status InOrderTraverse_NonRecursive(BiTree T, Status(*Visit)(TElemType e)){
Stack *S;
BiTree p;
S = (Stack *)malloc(sizeof(Stack));
InitStack(S);
Push(S, T); //根指標進棧
while (!StackEmpty(S)){
//向左走到盡頭
while (GetTop(S, &p) && p){
Push(S, p->lchild);
}
//空指標退棧
Pop(S, &p);
//訪問節點,並向右一步
if (!StackEmpty(S)){
Pop(S, &p);
if (!Visit(p->data))
return ERROR;
Push(S, p->rchild);
}
}
return OK;
}
//採用二叉連結串列儲存結構,Visit是對資料元素進行操作的應用函式,
//中序遍歷二叉樹的非遞迴演算法,對每個資料元素呼叫函式Visit。
Status InOrderTraverse_NonRecursive_2(BiTree T, Status(*Visit)(TElemType e))
{
Stack *S;
BiTree p = T;
S = (Stack *)malloc(sizeof(Stack));
InitStack(S);
while (p || !StackEmpty(S)){
//根指標進棧,遍歷左子樹
if (p){
Push(S, p);
p = p->lchild;
}
//根指標退棧,訪問根結點,遍歷右子樹
else{
Pop(S, &p);
if (!Visit(p->data))
return ERROR;
p = p->rchild;
}
}
return OK;
}
//後序遍歷二叉樹,非遞迴演算法
Status PostOrderTraverse_NonRecursive(BiTree T, Status(*Visit)(TElemType e)){
Stack *S;
BiTree p, pre=NULL;//pre指向已訪問過的最後一個結點。
S = (Stack*)malloc(sizeof(Stack));
InitStack(S);
Push(S, T);//根指標進棧
while (!StackEmpty(S)){
//獲取棧頂指標,如果當前結點有左子樹,並且左子樹結點不是剛被訪問的節點。如果當前結點有右子樹,並且右子樹結點不是剛被訪問的結點。
//表明棧頂指標指向的樹結點未被訪問,且左子樹和右子樹均未被訪問。此時,將結點的左子樹進棧。
if (GetTop(S, &p) && p->lchild && pre != p->lchild && !(p->rchild && pre == p->rchild))
Push(S, p->lchild);
//如果棧頂指標的右子樹存在,且未被訪問。則將右子樹進棧
else if (p->rchild && pre != p->rchild)
Push(S, p->rchild);
//如果左子樹和右子樹均被訪問過,則結點退棧,並進行訪問。更新pre。
else{
Pop(S, &p);
if (!Visit(p->data))
return ERROR;
pre = p;
}
}
return OK;
}
int main()
{
BiTree T;
CreatBiTree(&T);
//先序
printf("先序:\n");
PreOrderTraverse_NonRecursive(T, PrintElement);
printf("\n");
//中序
printf("中序:\n");
InOrderTraverse_NonRecursive(T, PrintElement);
printf("\n");
InOrderTraverse_NonRecursive_2(T, PrintElement);
printf("\n");
//後序
printf("後序:\n");
PostOrderTraverse_NonRecursive(T, PrintElement);
printf("\n");
system("pause");
return 0;
}