二叉树遍历算法

     二叉树的遍历是指按照一定次序访问二叉树中的所有节点,且每个节点仅被访问一次的过程。是最基本的运算,是其他运算的基础。

     二叉树有两种存储结构:顺序存储和链式存储

    顺序存储:  (对完全二叉树来说,可以充分利用存储空间,但对于一般的二叉树,只有少数的存储单元被利用)

typedef struct 
{
	ElemType data[MaxSize];
	int n;
}SqBTree;
  链式存储:

typedef struct node
{
	ElemType data;
	struct node *lchild;
	struct node *rchild;
} BTNode;

二叉树三种递归的遍历方法:

先序遍历访问根节点→先序遍历左子树→先序遍历右子树
中序遍历中序遍历左子树→访问根节点→中序遍历右子树
后序遍历后序遍历左子树→后序遍历右子树→访问根节点

二叉树遍历的递归算法:

void preOrder(BTNode *b)  //先序遍历递归算法
{
	if (b!=NULL)
	{
		visit(b);
		preOrder(b->lchild);
		preOrder(b->rchild);
	}
}
void InOrder(BTNode *b)   //中序遍历递归算法
{
	if(b!=NULL)
	{
		InOrder(b->lchild);
		visit(b);
		InOrder(b->rchild);
	}
}
void PostOrder(BTNode *b)   //后序遍历递归算法
{
	if(b!=NULL){
		PostOrder(b->lchild);
		PostOrder(b->rchild);
		visit(b);
	}
}

二叉树非递归遍历算法:

有两种方法:①用栈存储信息的方法  ②增加指向父节点的指针的方法    暂时只介绍下栈的方法

先序遍历

void PreOrder(BTNode *b)
{
	Stack s;
	while(b!=NULL||!s.empty())
	{
		if(b!=NULL){
			visit(b);
			s.push(b);
			b=b->left;
		}
		else{
			b=s.pop();
			b=b->right;
		}
	}
}
中序遍历:

void InOrder(BTNode *b){
	Stack s;
	while(b!=NULL||!s.empty()){
		if (b!=NULL)
		{
			s.push(b);
			s=s->left
		}
		if(!s.empty()){
			b=s.pop();
			visit(b);
			b=b->right;
		}
	}
}
后序遍历:

void PostOrder(BTNode *b){
	Stack s;
	while(b!=NULL){
		s.push(b);
	}
	while(!s.empty()){
		BTNode* node=s.pop();
		if(node->bPushed){
			visit(node);
		}
		else{
			s.push(node);
			if(node->right!=NULL){
				node->right->bPushed=false;
				s.push(node->right);
			}
			if(node->left!=NULL){
				node->left->bpushed=false;
				s.push(node->left);
			}
		node->bPushed=true;  //如果标识位为true,则表示入栈
		}		
	}
}
层次遍历算法:(用队列的方法)

void levelOrder(BTNode *b){
	Queue Q;
	Q.push(b);
	while(!Q.empty()){
		node=Q.front();
		visit(node);
		if(NULL!=node->left){
			Q.push(node->left);
		}
		if(NULL!=right){
			Q.push(node->right);
		}
	}
}
已知先序和中序求后序的算法:(已知后序和中序求先序的算法类似,但已知先序和后序无法求出中序)

int find(char c,char A[],int s,int e) /* 找出中序中根的位置。 */
{
	int i;
	for(i=s;i<=e;i++)
	if(A[i]==c) return i;
}
/* 其中pre[]表示先序序,pre_s为先序的起始位置,pre_e为先序的终止位置。 */
/* 其中in[]表示中序,in_s为中序的起始位置,in_e为中序的终止位置。 */
/* pronum()求出pre[pre_s~pre_e]、in[in_s~in_e]构成的后序序列。 */
void pronum(char pre[],int pre_s,int pre_e,char in[],int in_s,int in_e)
{
	char c;
	int k;
	if(in_s>in_e) return ; /* 非法子树,完成。 */
	if(in_s==in_e){printf("%c",in[in_s]); /* 子树子仅为一个节点时直接输出并完成。 */
	 return ;
	}
	c=pre[pre_s]; /* c储存根节点。 */
	k=find(c,in,in_s,in_e); /* 在中序中找出根节点的位置。 */
	pronum(pre,pre_s+1,pre_s+k-in_s,in,in_s,k-1); /* 递归求解分割的左子树。 */
	pronum(pre,pre_s+k-in_s+1,pre_e,in,k+1,in_e); /* 递归求解分割的右子树。 */
	printf("%c",c); /* 根节点输出。 */
}
main()
{
	char pre[]="abdc";
	char in[]="bdac";
	printf("The result:");
	pronum(pre,0,strlen(in)-1,in,0,strlen(pre)-1);
	getch();
}





评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值