二叉树非递归遍历

题记

二叉树的递归遍历比较简单,这里就不说了。二叉树非递归的实现要依赖栈,其中,后序遍历的非递归实现稍微复杂些。这里总结下,便于理解。

好了,不多说了,直接上代码,思路都在注释里。

代码部分:

#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

(全文完)

你可能感兴趣的:(二叉树非递归遍历)