基本思路,完全二叉树有这么一个性质,如果二叉树的root从下标为0的位置开始,若a节点的下标为i,那么它左儿子的下标为2i+1。右儿子为2i+2。(下标从1开始的话,左儿子的下标为2i,右儿子为2i+1)。
这个下标则为完全二叉树在层序遍历时的输出顺序。而对于任意一棵搜索树,其中序遍历的输出,是一个递增的数列。根据这两个性质,可以有如下算法。
首先,将输入的数列递增排序,会用到sort函数将输入的数据排序。这样,得到了所求的完全二叉搜索树的中序遍历输出,得到数组a[i]。接着,根据总的节点个数,将这个完全二叉搜索树的层序遍历的顺序(或者下标),中序遍历输出,得到数组b[i]。
即有一棵完全的二叉搜索树,每个节点上除了 data,left以及right以外,还有一个flag,用来记录他是第几个元素(按照层序遍历的顺序)。现在有它的中序遍历的输出,那么,只要在这个中序遍历的输出里面,按照每个节点对应的层序遍历的flag,输出,就是层序遍历的输出值了。
对于如何中序的输出层序遍历的顺序,可以参考如何中序的输出节点。类比得:终止条件,输入的 i 大于总的元素数N。递归的顺序,root的顺序是i,则先让2i+1入递归,然后输出i,接着让2i+2入递归。
#include "stdio.h"
int b[10]={};
void Sort(int a[])
{
for(int i=0;i<10;i++)
for(int j = 0; j<10-i-1;j++)
if(a[j]>a[j+1]){
int tmp = a[j];
a[j] = a[j+1];
a[j+1] = tmp;
}
}
void mid_tre(int root, int N,int a[])
{
if(root<=N){
static int i = 0;
mid_tre(root*2+1,N,a);
/*因为数组a从0开始,所以左子树root*2+1,如果数组a从1开始,则左子树root*2*/
b[root] = a[i++];
mid_tre(root*2+2,N,a);
}
}
int main()
{
int a[10];
for(int i =0; i<10; i++)
scanf("%d",&a[i]);
printf("\n");
Sort(a);
for(int i =0; i<10; i++)
printf("%d ",a[i]);
printf("\n");
mid_tre(0,9,a);
for(int i =0; i<10; i++)
printf("%d ",b[i]);
return 0;
}
我们还可以通过每次类似先序遍历的方法来解决问题
#include "stdio.h"
int a[10];
int b[10]={};
void Sort(int a[])
{
for(int i=0;i<10;i++)
for(int j = 0; j<10-i-1;j++)
if(a[j]>a[j+1]){
int tmp = a[j];
a[j] = a[j+1];
a[j+1] = tmp;
}
}
int GetLeftLength(int n)
{
int H=0,t = 1,X=1,Last;
int N=n+1;
while(N>1){
N/=2;
H++;
} //计算完全二叉树部分的H值
printf("H = %d\n",H);
for(int i=0;i<H;i++)
t*=2;
Last=n-t+1; //最后一层的节点数
for(int i=0;i<H-1;i++)
X*=2; //左子树是满树的情况下,左子树最后一层的结点数
if(Last <= X) //判断左子树是否满
return Last+(t-1)/2;
else
return X+(t-1)/2;
}
void solve(int ALeft,int ARight,int TRoot)
/*ALeft 当前树的最左端的下标,从0开始,ARight 当前树的最后端,从n-1开始*/
{
int n=ARight-ALeft+1;
if(n==0) return;
int Lnum = GetLeftLength(n); //计算n个结点的树中,左子树的结点的个数
b[TRoot] = a[ALeft+Lnum];
int LeftRoot = TRoot*2+1; //数组从0开始存储,则左孩子为2*n+1;
int RightRoot = LeftRoot +1;
solve(ALeft,ALeft+Lnum-1,LeftRoot); //遍历左子数
solve(ALeft+Lnum+1,ARight,RightRoot);
}
int main()
{
for(int i =0; i<10; i++)
scanf("%d",&a[i]);
Sort(a);
solve(0,9,0);
for(int i =0; i<10; i++)
printf("%d ",a[i]);
printf("\n");
for(int i =0; i<10; i++)
printf("%d ",b[i]);
return 0;
}