C语言 二叉树的遍历(递归和非递归)

#include <iostream>
#include <cstdio>
#include "biTree.h"
#include "cstdlib"
#define OVERFLOW -1
#include <stack>
using namespace std;

Status CreateBiTree( BiTree &T ) {
	int a;
	printf( "Creating BiTree .....\n" );
	printf( "input: <number>:" );
	scanf( "%d",&a );
	if ( a==0 ) {
		T=NULL;
		}
	else {
		T=( BiTree )malloc( sizeof( BiTNode ) );
		if ( !T )
			exit( OVERFLOW );
		T->data=a;
		CreateBiTree( T->lchild );
		CreateBiTree( T->rchild );
		}
	return OK;
	}

Status PreOrderTraverse( BiTree T,Status( * Visit )( TElemtype e ) ) {
	if ( T ) {
		Visit( T->data );
		PreOrderTraverse( T->lchild,Visit );
		PreOrderTraverse( T->rchild,Visit );
		}
	return OK;
	}

Status InOrderTraverse( BiTree T,Status( *Visit )( TElemtype e ) ) {
	if ( T ) {
		InOrderTraverse( T->lchild,Visit );
		Visit( T->data );
		InOrderTraverse( T->rchild,Visit );
		}
	return OK;
	}

Status PostOrderTraverse( BiTree T,Status( *Visit )( TElemtype e ) ) {
	if ( T ) {
		PostOrderTraverse( T->lchild,Visit );
		PostOrderTraverse( T->rchild,Visit );
		Visit( T->data );
		}
	return OK;
	}

Status InOrderTraverseNoDG( BiTree T,Status( *Visit )( TElemtype e ) ) {
	stack<BiTree> st;
	BiTree p=NULL;
	st.push( T );
	while ( !st.empty() ) {
		while ( ( p=st.top() )&&p ) {
			st.push( p->lchild );
			}
		st.pop();//走到头然后继续往右
		if ( !st.empty() ) {
			p=st.top();
			st.pop();
			if ( !Visit( p->data ) )
				return ERROR;
			st.push( p->rchild ); //输出根之后 在栈顶(当前节点)继续往左循环
			}
		}
	return OK;
	}


Status PreOrderTraverseNoDG( BiTree T,Status( *Visit )( TElemtype e ) ) {
	stack<BiTree> st;
	BiTree p=NULL;
	st.push( T );
	while ( !st.empty() ) {
		while ( ( p=st.top() )&&p ) {
			if ( !Visit( p->data ) )
				return ERROR;
			st.push( p->lchild );
			}
		st.pop();//走到头然后继续往右
		if ( !st.empty() ) {
			p=st.top();
			st.pop();
			st.push( p->rchild ); //输出根之后 在栈顶(当前节点)继续往左循环
			}
		}
	return OK;
	}




Status PostOrderTraverseNoDG( BiTree T,Status( *Visit )( TElemtype e ) )

	{
	/*
	   如果不使用标志位区分第几次到达根结点,
	   可以利用如下的后序遍历特征来完成:当栈顶元素(根)的右子树为空(即:无右孩子),
	   或者是右子树非空但是已遍历完,即右孩子恰好是刚才访问过的结点,
	   此时应访问栈顶结点,并在访问后退栈
	   否则,如果栈顶元素的右孩子非空且未遍历,
	   此时直接访问栈顶元素的右孩子而不退栈,
	   算法要点只是需要记住最近访问过的结点即可
	*/
	BiTree p=T;
	stack <BiTree> st;
	BiTree have_visited=NULL;
	while ( NULL!=p||!st.empty() ) {
		while ( NULL!=p ) {
			st.push( p );
			p=p->lchild;
			}
		p=st.top();
		if ( NULL==p->rchild||have_visited==p->rchild ) {
			Visit( p->data );
			st.pop();
			have_visited=p;
			p=NULL;
			}
		else {
			p=p->rchild;
			}
		}
	return OK;
	}

int main() {
	BiTree newBiT;
	CreateBiTree( newBiT );
	printf( "先序遍历结果\n" );
	PreOrderTraverse( newBiT,Visit );
	printf( "\n中序遍历结果\n" );
	InOrderTraverse( newBiT,Visit );
	printf( "\n后序遍历结果\n" );
	PostOrderTraverse( newBiT,Visit );
	printf( "\n---非递归中根---\n" );
	InOrderTraverseNoDG( newBiT,Visit );
	printf( "\n---非递归先根---\n" );
	PreOrderTraverseNoDG( newBiT,Visit );
	printf( "\n---非递归后根---\n" );
	PostOrderTraverseNoDG( newBiT,Visit );
	return 0;
	}


posted @ 2015-01-22 19:54  一杯半盏  阅读(564)  评论(0编辑  收藏  举报