看了很多题解,也知道这题有更简单的做法,但是还是根据陈老师的方法来实现一遍
关键点:1、首先是明确用数组来存这颗完全二叉树,那是最省最适合的
2、关键思路:
是对这一堆数进行排序
然后求出左子树的结点的个数
进而可以求出根节点,进行赋值
之后有一个难点是如何根据根结点(该数组是以0下标开始)求出左子树和右子树的根结点:
int Left = Troot*2+1;
int Right = Left+1;
再不断递归
void solve(int ALeft, int ARight, int Troot)
{
//ALeft为正在进行操作的数组的第一个数的下标, 同理ARight正在进行操作的数组的第一个数的下标
//Troot为当前根结点所在的数组的位置
//n为当前所求数组的个数
int n = ARight-ALeft+1;
if (n==0)
return;
//L为左子树的结点个数
int L = GetLefttree(n);
//求出根节点,进行赋值
T[Troot] = tree[L+ALeft];
//推出左子树和右子树的根节点的个数
int Left = Troot*2+1;
int Right = Left+1;
//递归左右子树
solve(ALeft, ALeft+L-1, Left);
solve(ALeft+L+1, ARight, Right);
}
3、如何求左子树的结点数:
首先明确(假如树的根节点为第一层, 即h = 1),则第n层有
pow(2, h-1);
总共n层树,有
pow(2, h)-1;
看如下图
X的值是不能超过pow(2, h-1);
4、还有个细节是如何进行排序,c语言的排序函数是qsort,之前用的是c++都是sort,这是第一次,记录下用法
int compare(const void*a, const void*b)
{
return *(int *)a - *(int*)b;
}qsort(tree, n, sizeof(int), compare);
tree为要排序数组的指针,可以用数组名
n为数组大小,即为要排序的大小
sizeof(int)为数组里的每一个元素的字节
compare为自定义的排序函数
代码:# include# include # include int n; int tree[1010]; int T[1010]; int GetLefttree(int num) { int a = num+1; a/=2; int sumh = 0; while (a) { sumh++; a/=2; } int x = num-pow(2, sumh)+1; if (x>pow(2, sumh-1)) x = pow(2, sumh-1); return pow(2, sumh-1)+x-1; } void solve(int ALeft, int ARight, int Troot) { int n = ARight-ALeft+1; if (n==0) return; int L = GetLefttree(n); T[Troot] = tree[L+ALeft]; int Left = Troot*2+1; int Right = Left+1; solve(ALeft, ALeft+L-1, Left); solve(ALeft+L+1, ARight, Right); } int compare(const void*a, const void*b) { return *(int *)a - *(int*)b; } int main() { scanf("%d", &n); for (int i=0; i



