二叉树的先序遍历、中序遍历、后序遍历-C语言描述

什么是先序、中序、后序

  • 先序遍历先访问根结点,再先序遍历左子树,再先序遍历右子树
  • 中序先中序遍历左子树,再访问根节点,再遍历右子树
  • 后序先遍历左子树,再遍历右子树,再访问根节点

各顺序的实质(窍门)

各顺序遍历走的路径相同,从根节点从左边开始绕着二叉树走,每个结点会遇到3次,先序就是第一次遇到结点就输出一次(或者其他操作),中序就是第二次碰到时输出,后序就是第三次碰到时输出。
image

递归实现

先序遍历的递归遍历算法

void PreOrderTraversal(BinTree BT)
{
	if(BT)
	{
		printf("%d",BT->Date);
		PreOrderTraversal(BT->Left);
  		PreOrderTraversal(BT->Right);
	}
}

中序遍历

void InOrderTraversal(Bintree BT)
{
	if(BT){
	InOrderTraversal(BT->Left);
	printf("%d",BT->Date);
	InorderTraversal(BT->Right);
	}
}

后序遍历

void PostOrderTraversal(BinTree BT)
{
	if(BT)
	{
		PreOrderTraversal(BT->Left);
  		PreOrderTraversal(BT->Right);
		printf("%d",BT->Date);
	}
}

堆栈循环实现

先序遍历的非递归循环算法

void PreOrderTraversal(BinTree BT)
{
	BinTree T=BT;
	Stack S=CreatStack(Maxsize);//创建并初始化堆栈
	while(T || !IsEmpty(S)){
		while(T){    //一直向左并将沿途结点压入堆栈
			printf("%d",T->Date);//第一次遇到时就打印
			push(S,T);
			T=T->Left;
		}
		if(!IsEmpty(S)){
			T=pop(S);//结点弹出堆栈
			T=T->Right;//转向右结点
		}
	}
}

中序遍历的非递归循环算法

  • 遇到一个节点把他压栈,并去遍历它的左子树
  • 当左子树遍历完成,弹出栈顶节点,并访问它
  • 然后根据其右指针中序遍历其右子树
void InOrdertraversal(BinTree BT)
{
	BinTree T=BT;
	Stack S=CreatStack(Maxsize);//创建并初始化栈
	while(T || !IsEmpty(S)){
		while(T){//中序遍历第二次碰到时再打印
			push(S,T);
			T=T->Left;
		}
		if(!IsEmpty(S)){
			T=pop(S);
			printf("%d",T->Date);
			T=T->Right;
			/*访问最左边的叶子结点时,打印了它本身,
			再将它的右子树(NULL)赋值给T,经过判断,
			就会弹出叶子结点的父元素。如果理解不了就记住。*/
		}
	}
}

后序遍历

image
从根节点开始,向左绕圈,第3次经过的节点并输出就是后序遍历
如果逆着来看,从右边开始绕圈,第1次经过的结点刚好是从左边绕圈第3次经过的结点
只不过方向刚好相反,我们可以把前序遍历的Left与Right交换位置,然后再用另一个栈记录每次遇到的结点
最后依次取出来

void PostOrderTraversal(BinTree BT)
{
	BinTree T=BT;
	Stack S=CreatStack(Maxsize);//创建并初始化堆栈
	Stack R=CreatStack(Maxsize);
	while(T || !IsEmpty(S)){
		while(T){    //一直向右并将沿途结点压入堆栈
			push(R,T);
			push(S,T);
			T=T->Right;
		}
		if(!IsEmpty(S)){
			T=pop(S);//结点弹出堆栈
			T=T->Left;
		}
	}
	while(!IsEmpty(R)){//R弹栈
		T=pop(R);
		printf("%d",T->Date);
	}
}

原文地址:https://www.cnblogs.com/sq800/p/15002586.html