題記
二叉樹的遞歸遍歷比較簡單,這裏就不說了。二叉樹非遞歸的實現要依賴棧,其中,後序遍歷的非遞歸實現稍微複雜些。這裏總結下,便於理解。
好了,不多說了,直接上代碼,思路都在註釋裏。
代碼部分:
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 30
typedef struct BSTreeNode{
int m_value;
struct BSTreeNode *m_pLeft;
struct BSTreeNode *m_pRight;
}BSTreeNode;
//先得寫個簡單的int棧
typedef struct stack{
BSTreeNode* data[MAXSIZE];
int top;
}Stack;
//-------- 棧的各種操作--------------------//
int isEmpty(Stack *s){
if(s->top == 0){
return 1;
}else{
return 0;
}
}
int push(Stack *s, BSTreeNode *node){
if(s->top>=MAXSIZE){
printf("error:棧已滿\n");
return -1;
}
s->data[s->top++] = node;
return 1;
}
BSTreeNode * pop(Stack *s){
if(s->top == 0){
printf("error:棧內沒有元素\n");
return NULL;
}
return s->data[--(s->top)];
}
//------- 樹的各種操作 --------------------------//
//生成二叉查找樹
BSTreeNode *insert(BSTreeNode *tree,BSTreeNode *n){
if(tree == NULL){
tree = n;
}else if(n->m_value < tree->m_value){
tree->m_pLeft = insert(tree->m_pLeft,n);
}else{
tree->m_pRight = insert(tree->m_pRight,n);
}
return tree;
}
//生成測試的二叉查找樹
BSTreeNode * create(){
int data[]={10,6,14,4,8,12,16};
int i;
BSTreeNode * tree=NULL;
for(i=0;i<sizeof(data)/sizeof(int);i++){
BSTreeNode *fresh = (BSTreeNode*)malloc(sizeof(BSTreeNode));
fresh->m_value = data[i];
fresh->m_pLeft = fresh->m_pRight = NULL;
tree = insert(tree,fresh);
}
return tree;
}
void destroy(BSTreeNode *cnode){
if(cnode!=NULL){
destroy(cnode->m_pLeft);
destroy(cnode->m_pRight);
free(cnode);
}
}
//Description:非遞歸前序遍歷
//Algorithm:
//沿着左指針訪問沿途經過的根節點,同時將右指針進棧,以便在遞歸訪
//問左子樹完成後能得到右子樹的根節點的地址,如此重複進行,直到棧空。
void preOrderTree(BSTreeNode *cnode){
Stack s;
s.top=0;
while( cnode || !isEmpty(&s)){
if(cnode){
printf("%d,",cnode->m_value);//輸出節點
if(cnode->m_pRight){
push(&s,cnode->m_pRight);//壓入右子樹節點
}
cnode = cnode->m_pLeft;
}else{
cnode = pop(&s);
}
}
}
//Description:非遞歸中序遍歷
//Algorithm:
//先沿着左指針走到二叉樹中最左下的結點,即左指針爲空的結點,將沿
//途經過的根節點,指針進棧。當左指針爲空時,從棧中取出根節點訪問,然後再跳
//到右子樹上。
void inOrderTree(BSTreeNode *cnode){
Stack s;
s.top = 0;//初始化棧
while(cnode || !isEmpty(&s)){
while(cnode){//將沿途的的左孩子壓棧
push(&s,cnode);
cnode = cnode->m_pLeft;
}
cnode=pop(&s);
//訪問該節點
printf("%d,",cnode->m_value);
//訪問右子樹
cnode = cnode->m_pRight;
}
}
//Description:非遞歸的後序遍歷
//Algorithm:先沿着左指針走到二叉樹中最左下的結點,將沿途經過的根節點指針進
//棧,若右子樹爲空,則彈棧並訪問根節點,否則,跳到右子樹上
void postOrderTree(BSTreeNode *cnode){
int flag[20]={0};//用於判斷該節點的右子樹是否已經被訪問過了!
Stack s;
s.top=0;
while(cnode || !isEmpty(&s)){
while(cnode){
push(&s,cnode);
flag[s.top-1]=0;//注意在這裏賦初值!而不是在一開始!
cnode = cnode->m_pLeft;
}
cnode = pop(&s);
if(cnode->m_pRight && flag[s.top] ==0){
push(&s,cnode);
flag[s.top-1]=1;//標記該節點的右子樹已經被訪問了
cnode = cnode->m_pRight;
}else{
printf("%d,",cnode->m_value);
cnode = NULL;//這個地方值得注意!讓其遞歸向上。
}
}
}
int main(){
BSTreeNode *tree = create();
preOrderTree(tree);
printf("\n");
inOrderTree(tree);
printf("\n");
postOrderTree(tree);
printf("\n");
destroy(tree);
return 0;
}
感謝 http://www.cnblogs.com/hicjiajia/archive/2010/08/27/1810055.html 和 數據結構課程 爲我寫這篇文章提供參考。
如果轉載請註明 blog.csdn.net/whuslei
(全文完)