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

首先明白两个概念:

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

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


PS:

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

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

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


直接上代码:

#include "stdlib.h"
#include 
#include 
#include 
using namespace std;

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

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

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

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

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

	while(!nodeStack.empty())
	{
		pNode = nodeStack.top();
		nodeStack.pop();
		cout<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<value<<" ";
	InOrderRecursive(parent->rightChild);
}

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

	stack 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<value<<" ";
		nodeStack.pop();
		pNode = pNode->rightChild;
	}
}

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

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

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

	stack 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<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 nodeQueue;
	BinaryTreeNode* pNode = NULL;
	nodeQueue.push(root);
	while(!nodeQueue.empty())
	{
		pNode = nodeQueue.front();
		cout<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<

欢迎各种指正、交流!

你可能感兴趣的:(C/C++,数据结构)