二叉树的各种遍历方法(非递归)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lingling_nice/article/details/80968006
#include<malloc.h>
#include<iostream>
#include<stack>
#include<queue>
using namespace std;
typedef  char ElemType;
typedef struct  BtNode
{
	BtNode *leftchild;
	BtNode *rightchild;
	ElemType data;
}BtNode,*BinaryTree;

先序遍历(非递归)

非递归就是利用栈的特性(先进后出),来进行模拟栈

void NicePreOrder(BtNode *p)
{
	 BtNode *s = NULL;
	 stack<BtNode* > st;
	 st.push(p);
	 while(!st.empty())
	 {
		 BtNode *node = st.top();st.pop();
		 cout<<node->data<<" ";
		 if( node->rightchild != NULL)
		 {
			 st.push(node->rightchild);
			 if(node->leftchild != NULL)
			 {
                             st.push(node->leftchild);
			 }
		 }
	 }
	 cout<<endl;
}

中序遍历(非递归)

//中序遍历
void NiceMiOrder(BtNode *p)
{
	BtNode *s = NULL;
	stack<BtNode* > st;
	while(p != NULL || !st.empty())
	{
		while(p != NULL)
		{
			st.push(p);
			p = p->leftchild;	
		}
		BtNode *node = st.top();st.pop();
	    cout<<node->data<<" ";
	    p = node->rightchild;
	}
	cout<<endl;
}

后序遍历(非递归)

方法一:

//后序遍历
//后序遍历递归定义:先左子树,后右子树,再根节点。
//后序遍历的难点在于:需要判断上次访问的节点是位于左子树,还是右子树。
//若是位于左子树,则需跳过根节点,先进入右子树,再回头访问根节点;
//若是位于右子树,则直接访问根节点。
void NiceLaOrder(BtNode *p)
{
	BtNode *s = NULL;
	stack<BtNode *> st;
	BtNode *tag = NULL;
	while(p != NULL || !st.empty())
	{
		while(p != NULL)
		{
			st.push(p);
			p = p->leftchild;
		}
		BtNode *node = st.top();st.pop();
		if(node->rightchild == NULL || node->rightchild == tag)
		{
			cout<<node->data<<" ";
			tag = node;
			node = NULL;///////////////
		}
		else
		{
			st.push(node);
			p = node->rightchild;
		}
		
	}
	cout<<endl;
} 

方法二:

//要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,先将其入栈。
//如果P不存在左孩子和右孩子,则可以直接访问它;
//或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。
//若非上述两种情况,则将P的右孩子和左孩子依次入栈
//这样就保证了每次取栈顶元素的时候,左孩子在右孩子前面被访问
//左孩子和右孩子都在根结点前面被访问。
void nice_last_order(BtNode *ptr)
{
	stack<BtNode *>  st;
	st.push (ptr);
	BtNode *pre=NULL;
	while(!st.empty())
	{ 
		ptr=st.top();
		//如果当前节点没有左右孩子,或者有左孩子或有孩子,但已经被访问输出,  
        //则直接输出该节点,将其出栈,将其设为上一个访问的节点  
		if((ptr->leftchild==NULL && ptr->rightchild==NULL) 
			||( pre && (ptr->leftchild==pre  || ptr->rightchild==pre)))
		{
			printf("%c  ",ptr->data);
			pre=ptr;//让pre记录Ptr之前访问的结点
			st.pop();
		}
		else
		{
			if(ptr->rightchild!=NULL)
			{
				st.push (ptr->rightchild);
			}
			if(ptr->leftchild!=NULL)
			{
				st.push (ptr->leftchild);
			}
		}
	}
}

层次遍历(非递归)

//二叉树的层序遍历
//二叉树的层序遍历,由于其层级的关系,需要借助队列实现,从左到右,自上而下
//一次将二叉树的各个结点入队,这样便可以保证输出的顺序是层序排列的
void level_order(BtNode *ptr)
{
	queue<BtNode *>  qu;
	if(ptr==NULL)
	{
		return;
	}
	qu.push(ptr);
	while(!qu.empty())
	{	
		ptr=qu.front();
		printf("%c  ",ptr->data);
		qu.pop();
		if(ptr->leftchild!=NULL)
		{
			qu.push(ptr->leftchild);
		}
		if(ptr->rightchild!=NULL)
		{
			qu.push(ptr->rightchild);
		}
	}
}

猜你喜欢

转载自blog.csdn.net/lingling_nice/article/details/80968006