【数据结构】【二叉树】三、二叉树的遍历(前序、中序、后序、层序)

二叉树的遍历

本文将逐渐把四种遍历方法(前序、中序、后序、层序)的代码都补充上来,其中前三种将列出递归、迭代(用栈实现)两种写法;层序则只有迭代(用队列实现)写法。

对前序、中序、后序三者来说,递归写法基本一致,比较简单;而对于前两者的迭代写法,也相对简单,模板类似;后序遍历的迭代写法则稍为复杂,涉及到二次入栈的问题,需要仔细学习。

一、前序遍历

先放代码:

void PreOrderTraverse(BiTNode *T)
{
    
    
	if(T == nullptr)
		return;
	printf("%c", T->data);
	PreOrderTraverse(T->leftChild);
	PreOrderTraverse(T->rightChild);
}

实现的遍历效果如下图所示:
在这里插入图片描述
前序遍历的效果:
从根节点开始,先挨个遍历左孩子,即图中①②③的顺序,每经过一个节点,就读取一个节点;
直到某个节点没有左孩子,就来到到这个节点的兄弟节点(在有兄弟节点的情况下。若没有,则退回到其父节点的兄弟节点。若还没有,则退回到父节点的父节点的兄弟节点……),然后把兄弟节点当作一棵新的二叉树的根,以同样的方法遍历;
兄弟节点遍历完后,退回到它的父节点的兄弟节点(在其父节点有兄弟节点的情况下。若没有,则退回到父节点的父节点的兄弟节点……),逐次递归,直到遍历完所有节点。
总之,在前序遍历中,父节点的兄弟节点非常重要,往往是退回的第一选择。

二、中序遍历:

代码:
递归方式:

void MidOrderTraverse(BiTNode *T)
{
    
    
	if(T == nullptr)
		return;
	MidOrderTraverse(T->leftChild);
	printf("%c",T->data);
	MidOrderTraverse(T->rightChild);	
}

迭代方式:(from 浙江大学《数据结构》P114)
解释:在按中序遍历二叉树时,遇到一个节点,就把它压栈,并去遍历它的左子树;当左子树遍历结束后,从栈顶弹出这个节点并访问它,然后按其右指针再去中序遍历该节点的右子树。

void InorderTraverse(BinTree BT)
{
    
    
	BinTree T = BT;
	stack<ElemType> stk;
	
	while(!stk.empty() || T) //这个判断条件老折磨人了,|| T是不太容易想到的
	{
    
    
		while(T)
		{
    
    
			stk.push(T);
			T = T->left;
		}
		
		T = stk.top();
		stk.pop();
		printf("%d\n", T->val);
		
		T = T->right;
	}
}

在这里插入图片描述

三、后序遍历

代码:

void BackOrderTraverse(BiTNode *T)
{
    
    
	if(T == nullptr)
		return;
	MidOrderTraverse(T->leftChild);
	MidOrderTraverse(T->rightChild);
	printf("%c",T->data);	
}

在这里插入图片描述
后序遍历的效果:
由代码可以看出,后序遍历是先遍历当前节点的左右孩子,再显示它自己。
总之,后序遍历的基本步骤可以认为是先左子树、后右子树,且先孩子、后父亲的顺序来的。

四、层序遍历

层序遍历是依靠栈来实现的,首先把根节点的压栈,然后弹出根节点,同时把根节点的左右孩子压栈;
然后弹出根节点的左后孩子节点,在弹出每个节点的同时,把它的孩子压栈……这样就实现了层序遍历。
如下图所示:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_39642978/article/details/111188498
今日推荐