資料結構 樹筆記-6 二叉樹的非遞迴先序遍歷
如下這棵二叉樹的先序遍歷結果為:ABDEFPC
針對於上面的這棵二叉樹,結合程式碼,講述遍歷過程:#include <stdio.h> #include <malloc.h>
//#define ElemType char typedef char ElemType;
typedef struct BiTNode{ ElemType data; struct BiTNode *lchild, *rchild; }BiTNode, *BiTree;
#define MAX 10000 typedef struct{ BiTree data[MAX]; int top; }SeqStack;
|
對上圖的二叉樹,按照程式碼的思路說明如何用非遞迴的方式遍歷一棵二叉樹:
|
void pre_order_nonrecursive(BiTree T) { SeqStack s; s.top = -1;
BiTree tmp = T;
while(tmp){// while1開始 while(tmp){// while2 開始 printf("%c",tmp->data);
if(tmp->rchild){ if(s.top == MAX-1){ exit(0); }else{ s.data[++s.top] = tmp->rchild; } } tmp = tmp->lchild; }// while2結束
if(s.top != -1){ tmp = s.data[s.top--]; } }// while1結束 printf("\n");}
tmp結點的來源: 如果tmp的左孩子不為空,就把這個左孩子更新給tmp; 否則, 如果棧不為空,就把棧頂元素彈出並更新給tmp; 如果棧為空,說明這棵二叉樹遍歷完畢 |
T = A tmp = T =A 列印A A的右孩子存在為結點C,不為空 s.stop = -1<10000,此時棧為空,棧不滿 把C(的地址)入棧,同時棧頂指標stop加1變為0
tmp=A的左孩子=B 列印B B的右孩子存在為結點P,不為空 s.stop = 0<10000,此時棧不滿 把P(的地址)入棧同時棧頂指標stop加1變為1
tmp=B的左孩子=D 列印D D的右孩子存在為結點E,不為空 s.stop = 1<10000,此時棧不滿 把E(的地址)入棧同時棧頂指標stop加1變為2
tmp=D的左孩子=空 s.stop = 2>-1,此時棧不空 從棧中彈出棧頂元素E給tmp, 同時棧頂指標stop減1變為1
tmp=E 列印E E沒有右孩子,不進行入棧操作
tmp=E的左孩子=F 列印F F沒有右孩子,不進行入棧操作
tmp=F的左孩子=空 s.stop = 1>-1,此時棧不空 從棧中彈出棧頂元素P給tmp, 同時棧頂指標stop減1變為0
tmp=P 列印P P沒有右孩子,不進行入棧操作
tmp=P的左孩子=空 s.stop = 0>-1,此時棧不空 從棧中彈出棧頂元素C給tmp, 同時棧頂指標stop減1變為-1
tmp=C 列印C C沒有右孩子,不進行入棧操作
tmp=C的左孩子=空 s.stop = -1,棧空,不能進行彈棧操作
Tmp=空
先序遍歷結束: 列印結果為ABDEFPC |
程式碼:
#include <stdio.h>
#include <malloc.h>
//#define ElemType char
typedef char ElemType;
typedef struct BiTNode{
ElemType data;
struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;
#define MAX 10000
typedef struct{
BiTree data[MAX];
int top;
}SeqStack;
void pre_order_nonrecursive(BiTree T)
{
SeqStack s;
s.top = -1;
BiTree tmp = T;
while(tmp){
while(tmp){
printf("%c",tmp->data);
if(tmp->rchild){
if(s.top == MAX-1){
exit(0);
}else{
s.data[++s.top] = tmp->rchild;
}
}
tmp = tmp->lchild;
}
if(s.top != -1){
tmp = s.data[s.top--];
}
}
printf("\n");
}
對上述程式碼 的 實現過程進行概述:
二叉樹的非遞迴先序遍歷 |
|
#define MAX 10000 |
巨集定義是簡單的符號代換,這裡MAX符號的含義是棧中最多存放10000個結點的地址 |
typedef struct{ |
自定義一個結構體型別用於 棧操作 |
BiTree data[MAX]; |
定義一個數組型別的變數,用於儲存棧中的元素 作為先序遍歷,棧中存放的都是樹中某個結點的右孩子 |
int top; |
定義棧的棧頂指標top,它始終指向棧頂元素 |
}SeqStack; |
|
void pre_order_nonrecursive(BiTree T) |
引數T:即將被遍歷的樹的 樹根地址 |
{ |
|
SeqStack s; |
宣告棧 |
s.top = -1; |
初始化棧的棧頂指標為-1,因為陣列的第一個元素的下標是0,而此時作為棧的這個數組裡面沒有存放資料 |
|
|
BiTree tmp = T; |
宣告一個結點指標型別的變數tmp用於遍歷樹,並初始化為樹根地址 |
|
|
while(tmp){ |
外層while迴圈: tmp結點一開始是根結點, 之後就是每一個左枝的最後一個右孩子, 也是從棧中彈出的棧頂元素 |
while(tmp){ |
內層while迴圈:遍歷窮盡結點tmp的左枝 |
printf("%c",tmp->data); |
先序遍歷:根左右,所以拿到一個不為空的結點的時候,應首先列印這個結點的資料 |
|
|
if(tmp->rchild){ |
如果當前這個結點有右孩子 |
if(s.top == MAX-1){ |
並且 如果棧滿 |
exit(0); |
棧的容量不足以支援後序的先序遍歷操作,立即退出程式,不繼續再做任何操作 |
}else{ |
並且 如果棧不滿 |
s.data[++s.top] = tmp->rchild; |
把當前結點的右孩子的地址存到棧中,因為它以及它的子樹還沒有被遍歷;同時作為資料進棧的配套棧操作,把棧指標加一 |
} |
|
} |
|
tmp = tmp->lchild; |
為了遍歷窮盡結點tmp的左枝,把tmp更新為當前結點的左孩子地址 |
} |
|
|
|
if(s.top != -1){ |
此時tmp結點的左枝遍歷窮盡, 如果棧不為空,需要彈出棧頂元素,並把tmp更新為這個元素, 這個棧頂元素是左枝上的最後一個有右孩子的結點的右孩子 |
tmp = s.data[s.top--]; |
|
} |
|
} printf("\n"); |
|
} |