二叉樹非遞歸遍歷

題記

二叉樹的遞歸遍歷比較簡單,這裏就不說了。二叉樹非遞歸的實現要依賴棧,其中,後序遍歷的非遞歸實現稍微複雜些。這裏總結下,便於理解。

好了,不多說了,直接上代碼,思路都在註釋裏。

代碼部分:

#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

(全文完)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章