二叉树非递归遍历的通用算法

二叉树的3中遍历策略,关键在于处理节点的时机不同:前序遍历是遇到节点时处理,中序是处理完左节点后再处理,而后序是在处理完左右节点后再处理。

使用非递归方法实现时,除了记录当前的节点的访问栈,还需要记录当前节点的状态。对于每一个节点,我们用0来表示尚未处理左右子节点,1表示仅仅处理完毕左节点,2表示左右节点都处理完毕。那么,前序,中序,后序遍历的唯一不同,无非是对节点处理的时机不同而已。


const int MAX=20;
typedef struct Node
{
	char data;
	struct Node*lchild;
	struct Node*rchild;
}BiTreeNode;

const int STATE_NONE=0;//尚未处理任何一个节点 
const int STATE_LEFT_DONE=1;//处理完左节点 
const int STATE_LEFT_RIGHT_DONE=2;//左右节点都已经处理完 


/*
 算法说明:初始时放入根节点,将其标记为左右节点尚未处理的状态 
 每个循环,从栈中取出一个节点和其状态,根据其当前状态转移到下一个状态
(很显然,你可以从状态转换机的角度解读这个算法)。 
 状态转换规则: STATE_NONE-->STATE_LEFT_DONE-->STATE_LEFT_RIGTH_DONE-->弹出栈 
 伴随状态的变化,还需要相应的操作,如将左右子节点放入栈中,或者将当前节点弹出栈;
 最重要的一点是,当当前节点的状态符合处理状态的要求时,就会处理该节点。
 */
void travese(BiTreeNode*T,int when)
{
	if(when!=STATE_NONE||when!=STATE_LEFT_DONE||when!=STATE_LEFT_RIGHT_DONE)
	 {
	 	printf("状态输入有误,请重新输入");
	 	exit(1);
	 }
	BiTreeNode*Stack[MAX]; //保存节点的栈
	int stackState[MAX];   //保存节点状态的栈 
	int top=0;
	Stack[++top]=T;			//根节点入栈
	stackState[top]=STATE_NONE;	//根节点状态入栈 
	
	while(top>0)
	{
		BiTreeNode *p=Stack[top];
		int state=stackState[top];
		
		if(state==when)    //当前状态可以处理节点
			printf("%2c",p->data);
		
		//3中状态之间的转换 
		switch(state)
		{
			case STATE_NONE:
								stackState[top]=STATE_LEFT_DONE;
								if(p->lchild)
								{
									Stack[++top]=p->lchild;
									stackState[top]=STATE_NONE; 
								}
								break;
			case STATE_LEFT_DONE:
								stackState[top]=STATE_LEFT_RIGHT_DONE;
								if(p->rchild)
								{
									Stack[++top]=p->rchild;
									stackState[top]=STATE_NONE; 
								}
								break;
			case STATE_LEFT_RIGHT_DONE:
									top--;
									break;																				
		}
			
	} 
	
}

原文链接:https://www.jianshu.com/p/8359c1369066

猜你喜欢

转载自blog.csdn.net/qq_16829085/article/details/83574065