基础数据结构算法_二叉树的恢复和非递归遍历

我把二叉树的恢复和遍历写在一起了,刚好恢复完之后就能遍历,上数据结构实验课的小伙伴有福了。

二叉树的恢复一定要中序序列,然后先序序列或后序序列的随便一个,其实原理都一样。

对于先序来说,第一个元素是树的根节点,重点来了,用这个节点去分割中序序列。(设该节点在中序序列中的位置为i)

那么对中序序列来说i左边的为左子树,i右边得为右子树。然后找出先序序列中的左右子树,递归的进行这步操作即可,

详细的看代码一目了然(函数前面有注释)。

我这里有一个简单的方法实现先序后序中序的非递归遍历。

以往我们实现层次遍历的时候要借助一个链表(队列也行 这里为了保证都先序中序后序遍历的一致性)

把首元素压入链表头,当链表非空使输出结果,如果有左右子树就把左右子树压入最后一个元素的后面,输出完之后把改元素删除。

这里的先序中序后序遍历也是一样。

只不过不是遇到元素就输出,而是先把左右子树的位置放好,比如对先序来说,他要把他的左右子树插到第一个元素的后面。

然后在输出,输出完之后删除,这时第一个元素变成了他的左子树(如果有的话),对左子树进行一样的操作,当链表为空时结束。

中序遍历的话是把左子树插到第一个元素的前面,把右子树插到他的后面。(具体操作看代码,稍微有点技巧)

后序遍历的话是把左右子树插到第一个元素的前面。

这里要用到链表的插入操作,由于插入和删除都是在表头处,所以时间复杂度和递归的一致,但是效率比递归更高,因为不要用到大量工作栈。

具体的细节问题看代码,单个的功能函数并不长,只不过我把他写到一起去了,可以直接看单个函数。

                #include<iostream>
		#include<vector>
		#include<list>
		using namespace std;
		
		typedef struct node
		{
			int value;
			node* left;
			node* right;
		}node;
		
		vector<int> pre;//先序序列 
	        vector<int> mid;//中序序列 
	        vector<int> pos;//后序序列 
	    
		
		//先序加中序恢复二叉树 
		void premidrecover(node* &T,int a,int b,int x,int y)
		{
			for(int i=x;i<=y;i++)
			{
				if(mid[i]==pre[a])
				{
					T->value=mid[i];
					
					if(x<=i-1)
					{
						T->left=new node;
						premidrecover(T->left,a+1,a+i-x,x,i-1);
					}
					else T->left=NULL;
					
					if(i+1<=y)
					{
						T->right=new node;
						premidrecover(T->right,b-(y-i-1),b,i+1,y);
					}
					else T->right=NULL;
					
					return ;
				}
			} 
		}
		
		//后序加中序恢复二叉树 
		void posmidrecover(node* &T,int a,int b,int x,int y)
		{
			for(int i=x;i<=y;i++)
			{
				if(mid[i]==pos[b])
				{
					T->value=mid[i];
					
					if(x<=i-1)
					{
						T->left=new node;
						posmidrecover(T->left,a,a+i-x-1,x,i-1);
					}
					else T->left=NULL;
					
					if(i+1<=y)
					{
						T->right=new node;
						posmidrecover(T->right,b-(y-i),b-1,i+1,y);
					}
					else T->right=NULL;
					
					return ;
				}
			} 
		}
		
		//先序非递归遍历 
		void previsit(node *T)
		{
			list<node> seq;
			seq.push_back(*T);
			while(!seq.empty())
			{
				node &e=seq.front();
				if(e.left==NULL&&e.right==NULL)
				{
					cout<<e.value<<" ";
					seq.pop_front();
				}
				else
				{
					if(e.right!=NULL)
						seq.insert(++seq.begin(),*e.right);
					if(e.left!=NULL)
						seq.insert(++seq.begin(),*e.left);
					e.right=e.left=NULL;
				}
			}
		}
		
		//中序非递归遍历 
		void midvisit(node *T)
		{
			list<node> seq;
			seq.push_back(*T);
			while(!seq.empty())
			{
				node &e=seq.front();
				if(e.left==NULL&&e.right==NULL)
				{
					cout<<e.value<<" ";
					seq.pop_front();
				}
				else
				{
					list<node>::iterator it=seq.begin();//中间指针 
					if(e.left!=NULL)
						seq.insert(it,*e.left);
					if(e.right!=NULL)
						seq.insert(++it,*e.right);
					e.right=e.left=NULL;
				}
			}
		}
		
		//后序非递归遍历 
		void posvisit(node *T)
		{
			list<node> seq;
			seq.push_back(*T);
			while(!seq.empty())
			{
				node &e=seq.front();
				if(e.left==NULL&&e.right==NULL)
				{
					cout<<e.value<<" ";
					seq.pop_front();
				}
				else
				{
					if(e.right!=NULL)
						seq.insert(seq.begin(),*e.right);
					if(e.left!=NULL)
						seq.insert(seq.begin(),*e.left);
					e.right=e.left=NULL;
				}
			}
		}
		
		//层次遍历
		void levelvisit(node *T)
		{
			list<node> seq;
			seq.push_back(*T);
			while(!seq.empty())
			{
			 	node e=seq.front();
			 	if(e.left!=NULL)
			 	    seq.push_back(*e.left);
			 	if(e.right!=NULL)
			 	    seq.push_back(*e.right);
			 	cout<<e.value<<" ";
			 	seq.pop_front();
			}
		}
		
		int main()
{
	    int n;
	    
	    //测试先序加中序恢复二叉树 
	    cout<<"输入元素个数:"<<endl; 
	    cin>>n;
	    pre.resize(n);
	    mid.resize(n);
	    cout<<"输入先序序列:"<<endl;
	    for(int i=0;i<n;i++) cin>>pre[i];
	    cout<<"输入中序序列:"<<endl;
	    for(int i=0;i<n;i++) cin>>mid[i];
	    node *head1=new node;
	    premidrecover(head1,0,pre.size()-1,0,mid.size()-1);
	    
	    cout<<"先序非递归遍历结果为:"<<endl;
	    previsit(head1);
	    cout<<endl<<"中序非递归遍历结果为:"<<endl;
	    midvisit(head1);
	    cout<<endl<<"后序非递归遍历结果为:"<<endl;
	    posvisit(head1); 
	    cout<<endl<<"层次遍历结果为:"<<endl;
	    levelvisit(head1);
	    
	    
	    //测试后序加中序恢复二叉树 
	    cout<<endl<<"输入元素个数:"<<endl;
	    cin>>n;
	    pos.resize(n);
	    mid.resize(n);
	    cout<<"输入后序序列:"<<endl;
	    for(int i=0;i<n;i++) cin>>pos[i];
	    cout<<"输入中序序列:"<<endl;
	    for(int i=0;i<n;i++) cin>>mid[i];
	    node *head2=new node;
	    posmidrecover(head2,0,pos.size()-1,0,mid.size()-1);
	    
	    cout<<"先序非递归遍历结果为:"<<endl;
	    previsit(head2);
	    cout<<endl<<"中序非递归遍历结果为:"<<endl;
	    midvisit(head2);
	    cout<<endl<<"后序非递归遍历结果为:"<<endl;
	    posvisit(head2); 
	    cout<<endl<<"层次遍历结果为:"<<endl;
	    levelvisit(head2);
	    
		return 0;			    
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值