二叉树的前中后序遍历

本文介绍二叉树的前序,中序和后序遍历,采用递归和非递归两种方式实现。除此之外,还介绍了对二叉树按层遍历的方法。对树的前中后序遍历是深度优先搜索的策略,因此用栈实现。对树的按层遍历是广度优先搜索,因此采用队列实现。
树的前序,中序和后序遍历,都是针对父节点而言的。

二叉树的定义

下面给出二叉树的定义:

struct Tree
{
	int value;
	Tree* pLeft;
	Tree* pRight;
};
typedef Tree* binaryTree;

递归实现前序,中序和后序遍历

递归实现前序,中序和后序遍历思路相同。前序遍历如果当前节点不为空,就打印该节点的数值,然后对左子树和右子数分别递归调用该函数。递归调用要注意停止的条件。

/* 递归实现前序遍历 */
void preOrderRecur(binaryTree T)
{
	if(T == NULL)
		return;


	printf("%d ",T->value);


	preOrderRecur(T->pLeft);
	
	preOrderRecur(T->pRight);
}


/* 递归实现中序遍历 */
void inOrderRecur(binaryTree T)
{
	if(T == NULL)
		return;


	inOrderRecur(T->pLeft);


	printf("%d ", T->value);


	inOrderRecur(T->pRight);
}


/* 递归实现后续遍历 */
void posOrderRecur(binaryTree T)
{
	if(T == NULL)
		return;


	posOrderRecur(T->pLeft);


	posOrderRecur(T->pRight);


	printf("%d ", T->value);
}

二叉搜索树的前,中,后序遍历

对于二叉搜索树前,中,后序遍历的结果分别有各自的特点:
对于下图
前序遍历结果为:15-6-3-2-4-7-13-9-18-17-20;
中序遍历结果为:2-3-4-6-7-9-13-15-17-18-20;
后序遍历结果为:2-4-3-9-13-7-6-17-20-18-15;
中序遍历的结果最明显,使得二叉查找树呈从小到大的状态排序。这个结果很有用,对于二叉树中查找第K大的元素,转为排序的链表。
前序遍历的结果特点是,第一个数15将整个二叉树分成两部分,一部分是6-3-2-4-7-13-9都小于15,另一部分18-17-20都大于15。对于这每一个小部分右可以这样分析,6-3-2-4-7-13-9由最前面的数6分成两个部分,一部分是3-2-4是小于6的部分,另一部分是7-13-9是大于6的部分。对于3-2-4可以继续这样分析,第一个数3将其分为两个部分。后面分析是一样的不在赘述。
后续遍历的特点与前序相似,做一点小的改变就行。

非递归实现先序遍历

递归方式实现遍历,递归就相当于一个栈,用函数栈来保存了数据,因此,非递归的方式就是用栈来现实遍历。
先序遍历的非递归实现经过一下步骤:
(1)将根节点压入栈;
(2)弹出栈顶元素,打印栈顶元素的值,如果该元素的右子树不为空,则先将右子数压入栈,如果该元素的左子树也不为空,则将该元素的左子树也压入栈;
(3)重复步骤2直到栈为空。

该方法与图的深度优先搜索是一样的,类似的实现。

/* 非递归实现先序遍历 */
void preOrderUnRecur(binaryTree T)
{
	if(T == NULL)
		return;


	stack<int> S;   //定义一个栈


	S.push(T); //压入根节点
	
	while(!S.empty())
	{
		//弹出栈顶元素
		binaryTree tempNode = S.top();
		S.pop();


		printf("%d ", tempNode->value);


		//先压入右子树,后压入左子树
		if(tempTree != NULL)
			S.push(tempNode->pRight);


		if(tempTree != NULL)
			s.push(tempNode->pLeft);
	}
}


非递归实现中序遍历

非递归实现中序遍历,经过以下步骤:

(1)定义一个当前节点,将根节点指针赋给当前节点;

(2)如果当前节点不为空,就将当前节点压入栈,并将当前节点更新为其左子树;

(3)如果当前节点为空,就弹出栈顶元素,并打印该元素值。然后将当前节点更新为该元素值的右子树;

(4)一直重复(2)或(3)直到栈为空而且当前元素值也为空。

/* 非递归实现中序遍历 */
void inOrderUnrecur(binaryTree T)
{
	if(T == NULL)
		return;


	stack<int> S;
	binaryTree tempNode = T;


	while(!S.empty() && tempNode == NULL)
	{
		if(tempNode->pLeft != NULL)
		{
			S.push(tempNode->pLeft);
			tempNode = tempNode->pLeft;
		}
		else
		{
			tempNode = S.top();
			printf("%d ",tempNode->value);
			S.pop();
			tempNode = tempNode.pRight;
		}
	}
}

非递归实现后序遍历

非递归实现后序遍历,经过以下步骤:

(1)定义两个栈S1和S2,S1作为零时存储,S2作为最终输出数据存储,将根节点指针压入S1;

(2)从S1总弹出栈顶元素,将该元素压入S2,将S1不为空的左右子树压入S1;

(3)重复2过程直到S1为空为止;

(4)最后依次弹出S2的数据,并打印就是后序遍历的结果。

/* 非递归实现后序遍历 */
void posOrderUnrecur(binaryTree T)
{
	if(T == NULL)
		return;


	stack<int> S1;
    stack<int> S2;
	binaryTree cur;
	
    S1.push(T);


	while(!S1.empty())
	{
		cur = S1.top();
		S1.pop();
		S2.push(cur);
		
		if(cur->left != NULL)
			S1.push(cur->left);
		if(cur->right != NULL)
			S1.push(cur->right);
	}
	
	while(!S2.empty())
	{
		cur = S2->top();
		S2.pop();
		printf("%d\n", S2->value);
	}
}

按层遍历二叉树

按层遍历就是二叉树的广度优先搜索

(1)将二叉树的根从头部压入队列

(2)从队列尾部弹出一个元素,打印该元素值,然后将如果该元素左子树不为空,则将该元素的左子树从头部压入队列,右子树相同的操作;

(3)重复过程2直到队列为空。

/* 按层遍历二叉树 */
//用一个队列保存数据
void floorOrder(binaryTree T)
{
	if(T == NULL)
		return;


	deque<int> Q;
	Q.push_back(T);
	
	while(!Q.empty())
	{
		binaryTree tempNode = Q.front();
		printf("%d ", tempNode->value);


		if(tempNode->pLeft != NULL)
			Q.push_back(tempNode.pLeft);


		if(tempNode->pRight != NULL)
			Q.push_back(tempNode.pRight);


		Q.pop_front();
	}
}
    原文作者:oscarwin
    原文地址: https://blog.csdn.net/shanghairuoxiao/article/details/73752446
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞