二叉树的创建及递归和非递归遍历

一直知道个大概,没动手实现过,今天自己总结了下,以下图二叉树为例:


下面是创建二叉树,递归和非递归遍历的完整代码实现如下。

#include <iostream>
#include <stdio.h>
#include <stack>
using namespace std;

typedef struct BinNode{
	char data;
	bool flag;           //后序非递归中的标记
	struct BinNode *lchild,*rchild;

}BinNode,*BinTree;
//按先序创建树 ABD##E##CF####
void creatTree(BinTree &T)
{	

	char c;
	cin>>c;
	if(c=='#')

		T=NULL;
	else{
		T=(BinTree)malloc(sizeof(BinNode));
		T->data=c;
		creatTree(T->lchild);
		creatTree(T->rchild);
		}
}
void visit(BinTree T)
{
	if(T->data!='#')
		cout<<T->data<<" ";
}
void preOrder(BinTree T)               //前序递归
{
	if(T)
	{
		visit(T);
		preOrder(T->lchild);
		preOrder(T->rchild);
	}
}
void inOrder(BinTree T)             //中序递归
{
	if(T)
	{
		inOrder(T->lchild);
		visit(T);
		inOrder(T->rchild);
	}
}
void postOrder(BinTree T)          //后序递归
{
	if(T)
	{
		postOrder(T->lchild);
		postOrder(T->rchild);
		visit(T);
	}
}
void preOrderUnrec(BinTree T)           //非递归前序遍历
{	
	BinTree p;
	p=T;
	stack<BinTree> s;
	while(p || !s.empty())
	{
		while(p)
		{
			visit(p);
			s.push(p);
			p=p->lchild;
		}
		if(!s.empty())
		{
			p=s.top();
			s.pop();
			
			p=p->rchild;
		}
	}
}
void inOrderUnrec(BinTree T)             非递归中序遍历
{	
	BinTree p;
	p=T;
	stack<BinTree> s;
	while(p || !s.empty())
	{
		while(p)
		{
		
			s.push(p);
			p=p->lchild;
		}
		if(!s.empty())
		{
			p=s.top();
			visit(p);
			s.pop();
			p=p->rchild;
		}
	}
}

void postOrderUnrec1(BinTree T)    //非递归后序遍历  这个思路更好理解一些,下面有解释
{	
	BinTree p,cur;
	BinTree pre=NULL;
	p=T;
	stack<BinTree> s;
	s.push(p);
	while(!s.empty())
	{
		cur=s.top();
		if((cur->lchild==NULL && cur->rchild==NULL)||((pre!=NULL)&&(pre==cur->lchild || pre==cur->rchild)))
		{
			visit(cur);
			s.pop();
			pre=cur;
		}
		else
		{
			if(cur->rchild)
				s.push(cur->rchild);
			if(cur->lchild)
				s.push(cur->lchild);
		
		}
	}
}
void postOrderUnrec2(BinTree T)    //非递归后序遍历
{	
	BinTree p,cur;
	
	p=T;
	stack<BinTree> s;
	p->flag=false;
	s.push(p);
	while(!s.empty())
	{

		cur=s.top();
	
		if(cur->flag==true)
		{
			visit(cur);
			s.pop();               
			
		}
		else
		{
			if(cur->rchild){
				cur->rchild->flag=false;
				s.push(cur->rchild);
			}
			if(cur->lchild){
				cur->lchild->flag=false;         // 左右节点为NULL时,开始要出栈     
				s.push(cur->lchild);
			}
			cur->flag=true;            //左右子节点入栈后,父节点标记为TRUE
		
		}
	}
}

int main()
{
	BinTree T;
	creatTree(T);
	cout<<"preOrder  :"<<endl;
	preOrder(T);           //前序
	cout<<endl;
	cout<<"preOrderUnrecursion  :"<<endl;
	preOrderUnrec(T);
	cout<<endl;
	cout<<"inOrder  :"<<endl;
	inOrder(T);            //中序
	cout<<endl;
	cout<<"inOrderUnrecursion  :"<<endl;
	inOrderUnrec(T);
	cout<<endl;
	cout<<"postOrder  :"<<endl;
	postOrder(T);         //后序
	cout<<endl;
	cout<<"postOrderUnrecursion  :"<<endl;
	postOrderUnrec1(T);
	cout<<endl;
	postOrderUnrec2(T);
	cout<<endl;
	return 0;
}

其中非递归的后序遍历第一种方法postOrderUnrec1(BinTree T) 的思想:要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,先将其入栈。如果P不存在左孩子和右孩子,则可以直接访问它;或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。若非上述两种情况,则将P的右孩子和左孩子依次入栈,这样就保证了每次取栈顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。该方法摘自http://www.cnblogs.com/dolphin0520/archive/2011/08/25/2153720.html


                
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值