二叉树遍历,深度有限遍历,广度优先遍历,前序中序后续优先遍历,层次遍历

首先明白两个概念:

1. 深度遍历包括前中后序遍历三种;

2. 广度优先遍历就是层次遍历。

PS:

前中后序遍历,如果使用递归遍历,都很简单易理解;

如果使用非递归方式,首先想到的就应该是使用栈结构来控制整个过程,因为递归也是利用栈来实现的;

前中后序遍历的非递归方式中,后序遍历的非递归方式相比较而言,略复杂。

直接上代码:

#include "stdlib.h"
#include <iostream>
#include <stack>
#include <queue>
using namespace std;

struct BinaryTreeNode
{
	int value;
	BinaryTreeNode* leftChild;
	BinaryTreeNode* rightChild;
};

/*
前序遍历递归方式
步骤:
	1.先处理当前节点
	2.递归处理完左支
	3.递归处理右支
*/
void PreOrderRecursive(BinaryTreeNode* parent)
{
	if(NULL == parent)
		return;

	cout<<parent->value<<" ";
	PreOrderRecursive(parent->leftChild);
	PreOrderRecursive(parent->rightChild);
}

/*
前序遍历非递归方式
说明:
	nodeStack栈用来记录未遍历的节点,而且节点的左右孩子也未遍历。所以遍历结束条件是栈空
	((想什么时候可以出栈(被遍历),因为是先序遍历,所以只要在栈顶,输出即可,再处理左右孩子))
	1.栈不空,则把栈顶元素出栈,并把其右左孩子依次压栈。这个顺序保证了,先父亲、后左孩子、最后右孩子的前序遍历
*/
void PreOrderStack(BinaryTreeNode* root)
{
	if (NULL == root)
		return;

	stack<BinaryTreeNode*> nodeStack;
	BinaryTreeNode* pNode = NULL;
	nodeStack.push(root);

	while(!nodeStack.empty())
	{
		pNode = nodeStack.top();
		nodeStack.pop();
		cout<<pNode->value<<" ";

		if(NULL != pNode->rightChild)
			nodeStack.push(pNode->rightChild);
		if(NULL != pNode->leftChild)
			nodeStack.push(pNode->leftChild);
	}
}

/*
中序遍历递归方式
步骤:
	1.先递归处理完左支
	2.再处理当前节点
	3.最后递归处理右支
*/
void InOrderRecursive(BinaryTreeNode* parent)
{
	if(NULL == parent)
		return;

	InOrderRecursive(parent->leftChild);
	cout<<parent->value<<" ";
	InOrderRecursive(parent->rightChild);
}

/*
中序遍历非递归方式
说明:
	nodeStack栈用来记录未遍历的节点,而且节点的左右孩子也未遍历。遍历结束条件是栈空且当前节点无效。
	((想什么时候可以出栈,肯定是左支已经处理完了,栈顶的才可以出栈,而且出栈之后马上处理右孩子节点))
	1.中序遍历输出当前节点前,应把左支所有节点遍历完毕。所以第一步就是循环查找最左下节点,并依次压栈,直到找到最左下节点(没有左孩子)
	2.中序是(左中右),既然没有左孩子,则可以直接出当前节点(在栈顶)
	3.然后从第一步循环处理当前节点的右孩子
*/
void InOrderStack(BinaryTreeNode* root)
{
	if (NULL == root)
		return;

	stack<BinaryTreeNode*> nodeStack;
	BinaryTreeNode* pNode = root;

	while(NULL != pNode || !nodeStack.empty())
	{
		while(NULL != pNode)
		{
			nodeStack.push(pNode);
			pNode = pNode->leftChild;
		}

		/*
		if (nodeStack.empty())
			return;
		不需要此检测
		1. 外层while条件如果是pNode不空,会进内层while,则nodeStack肯定不空;
		2. 外层while条件如果是nodeStack不空,更不需要此检测了。
		*/

		pNode = nodeStack.top();
		cout<<pNode->value<<" ";
		nodeStack.pop();
		pNode = pNode->rightChild;
	}
}

/*
后序遍历递归方式
步骤:
	1.先递归处理完左支
	2.再递归处理完右支
	3.最后处理当前节点
*/
void PostOrderRecursive(BinaryTreeNode* parent)
{
	if(NULL == parent)
		return;

	PostOrderRecursive(parent->leftChild);
	PostOrderRecursive(parent->rightChild);
	cout<<parent->value<<" ";
}

/*
后序遍历非递归方式
步骤:
	nodeStack栈用来记录未遍历的节点,而且节点的左孩子或右孩子也未遍历。遍历结束条件是栈空。
	((想什么时候可以出栈,1.没有左右孩子的可以出;2.有左右孩子,且左右孩子已经被遍历输出了,也可以出栈))
	用preNode记录最近遍历输出的节点
	1.检查是不是满足输出条件,如果满足,则输出;
	2.不满足,则说明有左或右孩子,且没被遍历,所以先把孩子压栈做处理,处理完之后再说当前节点的事情
*/
void PostOrderStack(BinaryTreeNode* root)
{
	if (NULL == root)
		return;

	stack<BinaryTreeNode*> nodeStack;
	BinaryTreeNode* pNode = NULL;
	BinaryTreeNode* preNode = NULL;
	nodeStack.push(root);

	while(!nodeStack.empty())
	{
		pNode = nodeStack.top();
		if ((NULL == pNode->leftChild && NULL == pNode->rightChild)
			|| (preNode!=NULL && (preNode == pNode->leftChild || preNode == pNode->rightChild)))
		{
			cout<<pNode->value<<" ";
			nodeStack.pop();
			preNode = pNode;
		}
		else
		{
			if (NULL != pNode->rightChild)
				nodeStack.push(pNode->rightChild);
			if (NULL != pNode->leftChild)
				nodeStack.push(pNode->leftChild);
		}
	}
}

/*
宽度优先遍历,层次遍历
步骤:
	队列用来记录未遍历的节点,而且节点的左孩子或右孩子也未遍历。如果队列空,则说明遍历结束。
	((想一想层次遍历就是,同层孙子辈的最后依次输出,同层叔父辈的依次输出,同层爷爷辈的一次输出;而且是辈份越长,越先输出;同层即同辈份的必须挨着,队列可以满足))
	1.输出队头的节点;
	2.把队头节点的儿子们赶紧地送到队尾去排队(因为叔父辈的在队列里挨着,所以保证了叔父辈的儿子们这一辈在队列里也是挨着的)
*/
void BreadthFirst(BinaryTreeNode* root)
{
	if (NULL == root)
		return;

	queue<BinaryTreeNode*> nodeQueue;
	BinaryTreeNode* pNode = NULL;
	nodeQueue.push(root);
	while(!nodeQueue.empty())
	{
		pNode = nodeQueue.front();
		cout<<pNode->value<<" ";
		nodeQueue.pop();

		if (NULL != pNode->leftChild)
			nodeQueue.push(pNode->leftChild);
		if (NULL != pNode->rightChild)
			nodeQueue.push(pNode->rightChild);
	}

}

// 测试
int main()
{
	// 空树
	BinaryTreeNode* nullTree = NULL;;

	// 单节点树
	BinaryTreeNode singleNode;
	singleNode.value = 1;
	singleNode.leftChild = NULL;
	singleNode.rightChild = NULL;

	// 左支树
	BinaryTreeNode leftSideTree;
	leftSideTree.value = 1;
	BinaryTreeNode leftSideNode2;
	leftSideNode2.value = 2;
	BinaryTreeNode leftSideNode3;
	leftSideNode3.value = 3;
	leftSideTree.leftChild = &leftSideNode2;
	leftSideTree.rightChild = NULL;
	leftSideNode2.leftChild = &leftSideNode3;
	leftSideNode2.rightChild = NULL;
	leftSideNode3.rightChild = NULL;
	leftSideNode3.leftChild = NULL;

	// 右支树
	BinaryTreeNode rightSideTree;
	rightSideTree.value = 1;
	BinaryTreeNode rightSideNode2;
	rightSideNode2.value = 2;
	BinaryTreeNode rightSideNode3;
	rightSideNode3.value = 3;
	rightSideTree.leftChild = NULL;
	rightSideTree.rightChild = &rightSideNode2;
	rightSideNode2.leftChild = NULL;
	rightSideNode2.rightChild = &rightSideNode3;
	rightSideNode3.leftChild = NULL;
	rightSideNode3.rightChild = NULL;

	// 完全二叉树
	BinaryTreeNode completeBinaryTree;
	completeBinaryTree.value = 1;
	BinaryTreeNode btNode2;
	btNode2.value = 2;
	BinaryTreeNode btNode3;
	btNode3.value = 3;
	BinaryTreeNode btNode4;
	btNode4.value = 4;
	BinaryTreeNode btNode5;
	btNode5.value = 5;
	BinaryTreeNode btNode6;
	btNode6.value = 6;
	BinaryTreeNode btNode7;
	btNode7.value = 7;
	completeBinaryTree.leftChild = &btNode2;
	completeBinaryTree.rightChild = &btNode5;
	btNode2.leftChild = &btNode3;
	btNode2.rightChild = &btNode4;
	btNode3.leftChild = NULL;
	btNode3.rightChild = NULL;
	btNode4.leftChild = NULL;
	btNode4.rightChild = NULL;
	btNode5.leftChild = &btNode6;
	btNode5.rightChild = &btNode7;
	btNode6.leftChild = NULL;
	btNode6.rightChild = NULL;
	btNode7.leftChild = NULL;
	btNode7.rightChild = NULL;

	cout<<endl<<"nullTree";
	cout<<endl<<"PreOrderRecursive:";
	PreOrderRecursive(nullTree);
	cout<<endl<<"PreOrderStack:";
	PreOrderStack(nullTree);
	cout<<endl<<"InOrderRecursive:";
	InOrderRecursive(nullTree);
	cout<<endl<<"InOrdeStack:";
	InOrderStack(nullTree);
	cout<<endl<<"PostOrderRecursive:";
	PostOrderRecursive(nullTree);
	cout<<endl<<"PostOrderStack:";
	PostOrderStack(nullTree);
	cout<<endl<<"BreadthFirst:";
	BreadthFirst(nullTree);
	cout<<endl;

	cout<<endl<<"singleTree";
	cout<<endl<<"PreOrderRecursive:";
	PreOrderRecursive(&singleNode);
	cout<<endl<<"PreOrderStack:";
	PreOrderStack(&singleNode);
	cout<<endl<<"InOrderRecursive:";
	InOrderRecursive(&singleNode);
	cout<<endl<<"InOrdeStack:";
	InOrderStack(&singleNode);
	cout<<endl<<"PostOrderRecursive:";
	PostOrderRecursive(&singleNode);
	cout<<endl<<"PostOrderStack:";
	PostOrderStack(&singleNode);
	cout<<endl<<"BreadthFirst:";
	BreadthFirst(&singleNode);
	cout<<endl;

	cout<<endl<<"leftSideTree";
	cout<<endl<<"PreOrderRecursive:";
	PreOrderRecursive(&leftSideTree);
	cout<<endl<<"PreOrderStack:";
	PreOrderStack(&leftSideTree);
	cout<<endl<<"InOrderRecursive:";
	InOrderRecursive(&leftSideTree);
	cout<<endl<<"InOrdeStack:";
	InOrderStack(&leftSideTree);
	cout<<endl<<"PostOrderRecursive:";
	PostOrderRecursive(&leftSideTree);
	cout<<endl<<"PostOrderStack:";
	PostOrderStack(&leftSideTree);
	cout<<endl<<"BreadthFirst:";
	BreadthFirst(&leftSideTree);
	cout<<endl;

	cout<<endl<<"rightSideTree";
	cout<<endl<<"PreOrderRecursive:";
	PreOrderRecursive(&rightSideTree);
	cout<<endl<<"PreOrderStack:";
	PreOrderStack(&rightSideTree);
	cout<<endl<<"InOrderRecursive:";
	InOrderRecursive(&rightSideTree);
	cout<<endl<<"InOrdeStack:";
	InOrderStack(&rightSideTree);
	cout<<endl<<"PostOrderRecursive:";
	PostOrderRecursive(&rightSideTree);
	cout<<endl<<"PostOrderStack:";
	PostOrderStack(&rightSideTree);
	cout<<endl<<"BreadthFirst:";
	BreadthFirst(&rightSideTree);
	cout<<endl;

	cout<<endl<<"completeBinaryTree";
	cout<<endl<<"PreOrderRecursive:";
	PreOrderRecursive(&completeBinaryTree);
	cout<<endl<<"PreOrderStack:";
	PreOrderStack(&completeBinaryTree);
	cout<<endl<<"InOrderRecursive:";
	InOrderRecursive(&completeBinaryTree);
	cout<<endl<<"InOrdeStack:";
	InOrderStack(&completeBinaryTree);
	cout<<endl<<"PostOrderRecursive:";
	PostOrderRecursive(&completeBinaryTree);
	cout<<endl<<"PostOrderStack:";
	PostOrderStack(&completeBinaryTree);
	cout<<endl<<"BreadthFirst:";
	BreadthFirst(&completeBinaryTree);
	cout<<endl;

	system("pause");
	return 0;
}

欢迎各种指正、交流!

时间: 2024-12-17 07:40:02

二叉树遍历,深度有限遍历,广度优先遍历,前序中序后续优先遍历,层次遍历的相关文章

数据结构之二叉树 (构造 拷贝构造 以及前序中序后续三种遍历方法)

首先二叉树的节点定义如下: struct BinaryNode {                  BinaryNode *_left;                  BinaryNode *_right;                  T _data;                 BinaryNode( T data ) :_data(data), _left( NULL), _right(NULL )                 {}; }; 二叉树的结构以及接口如下 te

二叉树的前序/中序/后续遍历(递归+非递归)

这几日又把二叉树的递归写了一遍,原来是用C写的,自己写了一个栈,这一次直接用的C++,使用了自带的栈结构.代码如下: 1 /************************************************************************* 2 > Author: Yves 3 > E-mail: [email protected] 4 > File Name: BiTreeNew.cpp 5 > Description: ... 6 > Cre

数据结构之二叉树(前序 中序 后续线索话非递归方式)

节点: enum LinkType {                  THREAD,                  LINK }; template<class T> struct ThredBinaryNode {                  ThredBinaryNode *_left;                  ThredBinaryNode *_right;                  LinkType _left_tag;                 

二叉树基础(创建方法,遍历方法(前序/中序/后序/层序、递归/非递归)

二叉树的创建及遍历是很多二叉树问题的基础,递归遍历逻辑清晰,代码简约漂亮,然则效率低下(所有递归方案的通病,非不得已不用递归): 非递归遍历高效,却不是能信手写出来的,特别是后续非递归遍历,相信很多资深码工也有这样的经历: 5年前学习了二叉树的非递归遍历,一个月前复习了并达到能熟练写出的程度,在不参考任何资料的情况下,今天却怎样也写不出来. 如果你也有过这种经历,恭喜你,这说明你是一个正常人…… 另一方面市面上有些国人写的教材,各种语法.逻辑错误层出不起,不知祸害了多少未来的码工,深感痛心. 印

二叉树的前序中序后序遍历相互求法

二叉树的前中后序遍历,他们的递归非递归.还有广度遍历,参见二叉树的前中后序遍历迭代&广度遍历和二叉树的前中后序遍历简单的递归 现在记录已知二叉树的前序中序后序遍历的两个,求另外一个.一般,这两个中一定有中序遍历. 1.已知前序和中序,求后序遍历: 前序:ABDECFG  中序:DBEAFCG 思路简单:前序的第一个节点就是根节点, 中序中找到根节点的位置,根节点之前是其左子树,之后是右子树   按此顺序,依次在左子树部分遍历,右子树部分遍历 C++ 代码: TreeNode *BinaryTre

前序+中序 = 二叉树(先序、中序、后序、层次遍历)

内心OS:我靠啊!!!我就是偷了一下懒!!!把先序遍历的代码COPY了两份,改成了中序和后序遍历.万万没想到啊!我忘了修改函数中递归函数的名字!!!找这个BUG花了我三个小时~~我哭啊~~,我还以为我的知识体系坍塌了呢?!!~ 总结,这是一道模板题,要先记住大体流程,然后反复练习. 输入格式: 第一行给出结点个数 N(1<=N<= 50) 第二行给出先序序列,共N个整数 第三行给出后序序列,共N个整数 输出格式: 第一行给出先序遍历结果: 第二行给出中序遍历结果: 第三行给出后续遍历结果: 第

算法进阶面试题03——构造数组的MaxTree、最大子矩阵的大小、2017京东环形烽火台问题、介绍Morris遍历并实现前序/中序/后序

接着第二课的内容和带点第三课的内容. (回顾)准备一个栈,从大到小排列,具体参考上一课.... 构造数组的MaxTree [题目] 定义二叉树如下: public class Node{ public int value; public Node left; public Node right; public Node(int data){ this.value=data; } } 一个数组的MaxTree定义如下: ◆ 数组必须没有重复元素 ◆ MaxTree是一颗二叉树,数组的每一个值对应一

前序中序后序遍历非递归实现

#include<iostream> #include<vector> #include<stack> #include<string> #include<algorithm> #include<numeric> using namespace std; class node{ public: int val; node* left; node* right; node():val(0),left(NULL),right(NULL){

hihocoder(第十周)二叉树(前序中序推后续)递推实现

题目 : 后序遍历 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在参与过了美食节之后,小Hi和小Ho在别的地方又玩耍了一阵子,在这个过程中,小Ho得到了一个非常有意思的玩具——一棵由小球和木棍连接起来的二叉树! 小Ho对这棵二叉树爱不释手,于是给它的每一个节点都标记了一个标号——一个属于A..Z的大写字母,并且没有任意两个节点的标号是一样的.小Hi也瞅准了这个机会,重新巩固了一下小Ho关于二叉树遍历的基础知识~就这样,日子安稳的过了两天. 这天,小Ho正好在求解