数组实现二叉树遍历以及有二求一
一、首先,我们先上二叉树的三种遍历-----先序遍历,中序遍历,后序遍历
先序遍历:--------父节点,左儿子,右儿子
简化来说:根节点先输出,然后输出左儿子,左儿子有自己的左儿子就输出···依次,直到后面的节点没有左儿子就输出其右儿子,之后和左儿子输出情况一样。
int a[10000];
void per(int root)//root从1开始
{
if(a[root]==0)
return ;
if(a[root*2]==0&&a[root*2+1]==0)
return ;
printf("%d ",a[root]);
per(root*2);
per(root*2+1);
}
特点:
1.第一个数是整个数的根节点,且先是左子树(以整个根的根节点来看),然后是右子树,得到先序遍历的数组,可以确定整个数的根。
中序遍历---------左儿子,父节点,右儿子
简化来说:
先扫遍(递归)所有的左儿子,从最后开始输出左儿子,期间,作为左儿子的根也被输出了,所以不用思索根的输出情况,之后再扫遍所有右儿子,从最后开始输出右儿子。
int a[10000];
void mid(int root)
{
if(a[root]==0)
return ;
if(a[root*2]==0&&a[root*2+1]==0)
return ;
mid(root*2);
printf("%d ",a[root]);
mid(root*2+1);
}
特点:
1.根节点的左边是其左子树所有成员,根节点右边,是其右子树所有成员。得到中序遍历,可以确定成员的大体位置(是左?是右?)
后序遍历---------左儿子,右儿子,父节点
简化来说:
先扫遍左儿子,再扫遍右儿子,最后输出父节点。
int a[100000];
void end(int root)
{
if(a[root]==0)
return ;
if(a[root*2]==0&&a[root*2+1]==0)
return ;
end(root*2);
end(root*2+1);
printf("%d ");
}
特点:
1.最后一个数是整个树的根节点,从后往前,先是右子树,再是左子树。
得到后序遍历的数组,可以确定整个数的根。
二、接下来说一下有二求一
已知中序遍历和后序遍历 -------得到先序遍历
重点是抓住中序遍历和后序遍历的特点,先找根,再找左右儿子----具体的代码中说明。
int tree[10000];//重构树
int behind[10000];//已知的后序遍历顺序
int mid[100000];//已知的中序遍历顺序
void buildtree(int root,int l,int r,int t)
//root是根节点下标根据后序遍历得到
//t是重构树的下标
{
if(l>=r) return ;
int flag;
for(int i=l; i<=r; i++){
if(behind[root]==mid[i]){//找到根节点在中序遍历中的位置,这样好找他的左右儿子
flag=i;
}
}
tree[t]=mid[flag];
buildtree(root+flag-r-1,l,flag-1,t*2);//先创建左子树----中序遍历左边左子树。
buildtree(root-1,flag+1,r,t*2+1);
}
已知先序遍历和中序遍历-------得到后序遍历
重点也是抓住特点,方法和上一个基本相同。
int tree[10000];//重构树
int front[10000];//已知的先序遍历顺序
int mid[100000];//已知的中序遍历顺序
void buildtree(int root,int l,int r,int t)
//root是根节点下标根据先序遍历得到
//t是重构树的下标
{
if(l>=r) return ;
int flag;
for(int i=l; i<=r; i++){
if(front[root]==mid[i]){//找到根节点在中序遍历中的位置,这样好找他的左右儿子
flag=i;
}
}
tree[t]=mid[flag];
buildtree(root+1,l,flag-1,t*2);//先创建左子树----中序遍历左边左子树。
buildtree(root+flag-l+1,flag+1,r,t*2+1);
}
由于还是小白,暂时会的就这么多---------以后再补充吧。