1. 程式人生 > >建立二叉樹,實現二叉樹的先序遍歷、中序和後序遍歷的非遞迴演算法

建立二叉樹,實現二叉樹的先序遍歷、中序和後序遍歷的非遞迴演算法

先序遍歷:若二叉樹為空,則空操作;否則訪問根節點;先序遍歷左子樹;先序遍歷右子樹。
中序遍歷:若二叉樹為空,則空操作;否則中序遍歷左子樹;訪問根節點;中序遍歷右子樹。
後序遍歷:若二叉樹為空,則空操作;否則後序遍歷左子樹;後序遍歷右子樹;訪問根節點。

/*
* 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; }

這裡寫圖片描述