二叉树的遍历

转载请注明  t1234xy4 原创:http://blog.csdn.net/t1234xy4/article/details/51579416

二叉树的遍历:

源码下载点:http://download.csdn.net/detail/t1234xy4/9540560

二叉树的遍历有递归与非递归之分,使用非递归的遍历在性能上和健壮性上都优于递归。通常能使用非递归的情况下,都不用递归。

二叉树的遍历分为 先序、中序、后序遍历

使用递归的实现代码极其简单

先序:BinaryTreeDLR

void BinaryTreeDLR(BinaryTreeNode* root)
{
	if(root == NULL)	return ;
	 printf("%4d",root->m_Value);
	 BinaryTreeDLR(root->m_pLeft);
	 BinaryTreeDLR(root->m_pRight);
}

中序:

<pre name="code" class="cpp">void BinaryTreeLRD(BinaryTreeNode* root)
{
	if(root == NULL)	return ;
	 BinaryTreeLRD(root->m_pLeft);
	 BinaryTreeLRD(root->m_pRight);
         printf("%4d",root->m_Value);
}

 后序: 

void BinaryTreeLRD(BinaryTreeNode* root)
{
	if(root == NULL) return;

	BinaryTreeLRD(root->m_pLeft);
	BinaryTreeLRD(root->m_pRight);
	printf("%4d",root->m_Value);
}

使用非递归遍历相对比较复杂,我来总结一下需要注意的点和非递归的方法:

先序:

1、使用一个栈saveReturnNode,我的想法是保存当前节点的右节点,如果存在。

void BinaryTreeDLRNoRecursion(BinaryTreeNode* root)
{
	if(root == NULL)	return ;
	
	std::stack<BinaryTreeNode*> saveReturnNode;

	while(root != NULL || !saveReturnNode.empty())
	{
		if(root == NULL){	
			root =	saveReturnNode.top();
			saveReturnNode.pop();
		}

		printf("%4d",root->m_Value); //D
		if(root->m_pRight!=NULL)
			saveReturnNode.push(root->m_pRight); //R
		
		root = root->m_pLeft;//L
	}
}

中序:

1、使用一个saveReturnNode栈保存当前节点,令一个bool isPop来判定是否取至于栈;存在左子树就压栈,遇到叶子节点就开始退栈;然后检查每个退栈的节点是否有右子树。

很凌乱,只要记住:1、使用栈保存当前节点;2、使用一个bool判定是否遍历过;

void BinaryTreeLDRNoRecursion(BinaryTreeNode* root)
{
	if(root == NULL) return ;

	std::stack<BinaryTreeNode*> saveReturnNode;
	bool isPop = false;
	while (root	!= NULL || !saveReturnNode.empty())
	{
		if(root == NULL){ 
			root = saveReturnNode.top();
			saveReturnNode.pop();
			isPop = true;
		}

		if(root->m_pLeft!=NULL && !isPop){
			saveReturnNode.push(root);
			root = root->m_pLeft;
			isPop = false;
		}else
		{
			printf("%4d",root->m_Value);
			root = (root->m_pRight)?(root->m_pRight):NULL;
			isPop =false;
		}	
	}
}
2、利用中序遍历的顺序,来记住遍历方法。1、遇到存在左子树的压栈;2、访问节点在退栈之前 ;3 退栈后检查再是否存在右节点,存在进入右节点

void BinaryTreeLDRNoRecursion2(BinaryTreeNode* root)
{
	if (root == NULL) return;
	
	std::stack<BinaryTreeNode*> saveReturnNode;

	while(root!=NULL || !saveReturnNode.empty())
	{
		if (root == NULL) 
		{
			root = saveReturnNode.top();
			printf("%4d",root->m_Value);
			saveReturnNode.pop();

			root = (root->m_pRight)?(root->m_pRight):NULL;
		}else
		{
			saveReturnNode.push(root);
			root = root->m_pLeft;
		}
	}
}

后序:

后序遍历需要特别注意:1、栈saveReturnNode保存当前节点;2、需要记住上一次遍历的节点Pre,如果root存在右子树且Pre == root->right ;则说明已经遍历过了右子树,此时应该退栈。

void BinaryTreeLRDNoRecursion(BinaryTreeNode* root)
{
	if(root == NULL) return ;
	std::stack<BinaryTreeNode *> saveNode;
	BinaryTreeNode* Pre = NULL;

	while(root!=NULL || !saveNode.empty())
	{
		if (root == NULL)
		{
			root = saveNode.top();
			
			if(root->m_pRight != NULL && root->m_pRight!=Pre )
				root = root->m_pRight;
			else
			{
				Pre = root;
				printf("%4d",root->m_Value);
				saveNode.pop();
				root = NULL;
			}
		}else
		{
			saveNode.push(root);
			root = root->m_pLeft;
		}	
	}
}

自己实现的代码,难免会存在错误和bug,希望广大网友在学习的时候发现了在下面指出来,让其他人少走弯路!






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值