我把二叉树的恢复和遍历写在一起了,刚好恢复完之后就能遍历,上数据结构实验课的小伙伴有福了。
二叉树的恢复一定要中序序列,然后先序序列或后序序列的随便一个,其实原理都一样。
对于先序来说,第一个元素是树的根节点,重点来了,用这个节点去分割中序序列。(设该节点在中序序列中的位置为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;
}