二叉树遍历

二叉树的遍历:
遍历二叉树根据根节点,左子树和右子树的访问顺序可分为先序遍历,中序遍历和后序遍历。

一:设计思想:
递归遍历:由二叉树的递归定义可知:二叉树是由3个基本单元组成的:根结点,左子树和右子树。因此,若是能依次遍历这三部分,便是访问了整个二叉树。其中左子树或右子树又是一棵新的具有根结点,左子树和右子树的二叉树。遍历左子树或右子树又是在重新遍历一棵新的二叉树。遍历二叉树时又在调用遍历二叉树方法本身,因而可以使用递归算法。

非递归算法:为了实现非递归遍历算法,我们需要一个栈或队列作为实现算法的辅助数据结构,栈用于存放在遍历过程中待处理的任务线索。二叉树是非线性数据结构,遍历过程中涉及的每一个结点,都可能有左、右两棵子树,任何时刻程序只能访问其中之一,所以程序必须保留以后继续访问另一棵子树的线索。这里使用堆栈来保留继续遍历的线索。

下面给出的是用递归算法实现二叉树先序遍历的源代码:

void PreorderRecursive(BinaryTree Binary)
{
	BinaryNode *p=Binary;
	if(p)
	{
		visit(p->date);
		PreorderRecursive(p->lchild);
		PreorderRecursive(p->rchild);
	}
}

下面给出的是用递归算法实现二叉树中序遍历的源代码:

void MidorderRecursive(BinaryTree Binary)
{
	BinaryNode *p=Binary;
	if(p)
	{
		PreorderRecursive(p->lchild);
		visit(p->date);
		PreorderRecursive(p->rchild);
	}
}

下面给出的是用递归算法实现二叉树后序遍历的源代码:

void PostorderRecursive(BinaryTree Binary)
{
	BinaryNode *p=Binary;
	if(p)
	{
		PreorderRecursive(p->lchild);
		PreorderRecursive(p->rchild);
		visit(p->date);
	}
}

下面给出的是用非递归算法实现二叉树层次遍历的源代码:

void  leveltra(BinaryTree Binary)
{
	QueueList *Q;
	Q=InitQueue();
	BinaryNode *p;
	p=InitBinaryNode();
	p=Binary;
	EnQueue(Q,p);
	while (!QueueEmpty(Q))
	{
		p=DeQueue(Q);
		visit(p->date);
		if(p->lchild)
		EnQueue(Q,p->lchild);
		if(p->rchild)
		EnQueue(Q,p->rchild);
	}
}

下面给出的是用非递归算法实现二叉树先序遍历的源代码:

void  Preorder(BinaryTree Binary)
{
	StackList L;
	L=InitStack();
	BinaryNode *p;
	p=Binary;
	do{
		//弹栈,找有右孩子的结点的右孩子
		if(!StackEmpty(L))							//这里if和while语句换位置是为了可以访问到最后一个元素 
			{
				p=Pop(L);				//现在p指向右孩子
			}
		while(p)
		{
			visit(p->date);
			if(p->rchild)		//这里判断了只有遍历的结点有右孩子才会进栈,所以后边弹栈的时							//候不需要用do while语句来找右孩子,省去遍历空结点 
			{
				Push(L,p->rchild);
			}
			p=p->lchild;
		}
			
	}while(!StackEmpty(L));
}

下面给出的是用非递归算法实现二叉树中序遍历的源代码:

void Midorder(BinaryTree Binary)		//左根右 ,将每棵树的根压入栈中,先去遍历左子树,直到为空,
{
	StackList L;
	L=InitStack();
	BinaryNode *p;
	p=Binary;
	
	do
	{
		while(p)
		{
			Push(L,p);
			p=p->lchild; 
		}
		p=Pop(L);
		visit(p->date);
		p=p->rchild; 
	}while(p|| !StackEmpty(L));	
}

下面给出的是用非递归算法实现二叉树后序遍历的源代码:

下面给出的是用非递归算法实现二叉树后序遍历的源代码:
void  Postorder(BinaryTree Binary)	//左右根
{
	StackList L;
	L=InitStack();
	BinaryNode *p;
	p=Binary;
	bool state=false;
	do
	{
		while(p) 
		{
			Push_state(L,p,state);//同中序遍历,将沿途根结点入栈,第一次入栈state为false 
			p=p->lchild;
		} 
		if(!StackEmpty(L))
		{
			p=Pop_state(L,state); 	//弹出根结点,并取得对应state 
			if(state==false) 		/
			{  
				state=true;			//所以此时将其压回栈,并访问右子树,
				Push_state(L,p,state);//这是需要将其对应state标志为true,
				p=p->rchild;
			}
			else{ 					//右子树访问完,可以visit 
				visit(p->date);
				p=NULL;			//目的是表示此子树访问完,强制弹栈使之回到上一个根结点 
			}
		}
	}
	while(!StackEmpty(L));
}

以下为二叉树结点结构体类型的声明:

typedef struct BinaryNode{
	char date;
	struct BinaryNode *lchild;
	struct BinaryNode *rchild; 
}BinaryNode,*BinaryTree;
BinaryNode *InitBinaryNode(){
	BinaryNode *b;
	b=(BinaryNode *)malloc(sizeof(BinaryNode));
	b->lchild=NULL;
	b->rchild=NULL;
	return b; 
}

BinaryNode *CreateBiTree(BinaryNode *Binary){
	char ch;
	ch=getchar();
	if(ch=='#') return NULL;	//binary=NULL; 
	else{
		Binary=InitBinaryNode();
		Binary->date=ch;
  		Binary->lchild=CreateBiTree(Binary->lchild);
		Binary->rchild=CreateBiTree(Binary->rchild); 
	}		
	return Binary;
} 

以下为实现非递归算法所需要的栈和队列的相关代码:

void visit(char ch)
{
	printf("%c  ",ch);
}

/*-------------------------------------------------------------------------------栈的定义和相关方法-------*/ 
//定义栈	这里的栈存取的是二叉树节点,注意返回和输入的类型 
typedef struct StackNode{
	bool state;							//后序遍历需要一个指示状态的bool 
	BinaryNode *date;
	struct StackNode *next;
} StackNode,*StackList;
//栈的相关方法:

StackNode *InitStack()
{
	StackNode *L;
	L=(StackNode *)malloc(sizeof(StackNode));
	if(!L)
	{
		exit (-1);
	}
	L->state=false;
	L->next=NULL;
	L->date=NULL;
	return L;
}


BinaryNode *Pop(StackList L)
{
	BinaryNode *b;
	StackNode *p;
	b=InitBinaryNode();
	p=InitStack();
	p=L->next;
	b=p->date;
	L->next=p->next;
	free(p);
	return b;
} 

void Push(StackList L,BinaryNode *b)
{
	StackNode *p;
	p=InitStack();
	p->date=b;
	p->next=L->next;
	L->next=p;
}

BinaryNode *Pop_state(StackList L,bool &state)
{
	BinaryNode *b;
	StackNode *p;
	b=InitBinaryNode();
	p=InitStack();
	p=L->next;
	b=p->date;
	state=p->state;
	L->next=p->next;
	free(p);
	return b;
}
void Push_state(StackList L,BinaryNode *b,bool state)
{
	StackNode *p;
	p=InitStack();
	p->date=b;
	p->next=L->next;
	p->state=state;
	L->next=p;
}

bool StackEmpty(StackList L)
{
	if(L->next==NULL)
	return true;
	else
	return false;	
}

/*-------------------------------------------------------------------------------栈的定义和相关方法-------*/ 

/*-------------------------------------------------------------------------------队列的定义和相关方法-------*/ 
//队列	这里队列存的也是二叉树节点  注意参数控制 
typedef struct QueueNode
{
	BinaryNode *date;
	struct QueueNode *next;
	
}QueueNode;

typedef struct QueueList{
	QueueNode *front;
	QueueNode *rear;
}QueueList;
//初始化 	此处写的队列也带头结点 
QueueList *InitQueue()
{
	QueueNode *Q;
	QueueList *QL;
	Q=(QueueNode *)malloc(sizeof(QueueNode));
	QL=(QueueList *)malloc(sizeof(QueueList));
	if((!Q)||!(QL))
 		exit (-1);
	Q->date=NULL;
	Q->next=NULL;
	QL->front=QL->rear=Q;	//开始让头尾都指向头结点 
	return QL;
}
//判空:
bool QueueEmpty(QueueList *Q)
{
	if(Q->front==Q->rear)
	return true;
	else return false;
} 
//入队
void EnQueue(QueueList *Q,BinaryNode *b)
{
	QueueNode *q=(QueueNode *)malloc(sizeof(QueueNode));
	q->date=b;
	q->next=NULL;
	Q->rear->next=q;
	Q->rear=q;
} 
//出队
BinaryNode *DeQueue(QueueList *Q)
{
	if(!QueueEmpty(Q)){
		QueueNode *q;
		BinaryNode *b;
		q=(QueueNode *)malloc(sizeof(QueueNode));
		b=InitBinaryNode();
		q=Q->front->next;
		b=q->date;
		Q->front->next=q->next;
		if(Q->rear==q)
			Q->rear=Q->front;	
		free(q);
		return b;
	}else exit(-1);	
} 
/*-------------------------------------------------------------------------------队列的定义和相关方法-------*/ 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值