该二叉树是完全二叉树,完全二叉树因为堆这种高效的算法才显得完全二叉树如此重要。
堆具有以下性质的完全二叉树
大顶堆的根节点值比左右节点值都大
小顶堆的根节点值比左右节点值都小
实现:
1、初始完全二叉树
要从小到大排序,需要构造大顶堆,从最底层开始构造比如0 7 4 需要将0和7换一下位置,此时就变成了
第二步会对6 9 7 进行构造变成
第三步在对2 7 3 进行构造的时候会将2和7互换位置,并且4和2也会互相调换位置,就变成了
最终调整为
#include <iostream>
using namespace std;
void swap(int k[], int i, int j)//参数互换函数
{
int temp;
temp = k[i];
k[i] = k[j];
k[j] = temp;
}
//构造大顶堆函数
void HeapAdjust(int k[], int s, int n)
{
int i;
int temp;
temp = k[s];
for (i = 2 * s; i <= n; i = i * 2) //i = 2 * s表示该节点的左孩子
{
if (i<n && k[i] < k[i + 1])//k[i]左孩子 k[i+1]右孩子
{
i++;//使i指向最大的元素
}
if (temp >= k[i])
{
break;
}
k[s] = k[i];//将大值赋值给根节点
s = i;
}
k[s] = temp;
}
void HeapSort(int k[], int n)
{
// 5
// 2 6
// 0 3 9 1
//7 4
//构造一个大顶堆
int i;
for (i = n / 2; i > 0; i--)//n=9 n/2=4也就是需要先从底层开始构造大顶堆,将4号位置0换成比左右节点大的数
{
HeapAdjust(k, i, n);//构造大顶堆的函数,从i根节点下面的左右节点开始构造大顶堆
}
//构造完成之后,将第一个与最后一个进行互换
for (i = n; i > 1; i--)
{
swap(k, 1, i);//将第一与最后一个进行互换
HeapAdjust(k, 1, i-1);//互换完之后,重新构造一下,从1开始到i-1进行调整,因为最大值在后面已经排序好,只需要动前面就可以
}
}
int main()
{
int n = 0;
int a[] = { -1,5,2,6,0,3,9,1,7,4 };//完全二叉树在遍历的时候是从1开始的为了满足在左子树为2i右子树为2i+1,所以在0号位置补一个没用的元素,
//数组a构成的完全二叉树为下列形状,需要转换成大顶堆形式
// 5
// 2 6
// 0 3 9 1
//7 4
n = sizeof(a) / sizeof(*a);
HeapSort(a, n-1);
printf("排序后的结果是:");
for (int i = 1; i < n; i++)
{
printf("%d ", a[i]);
}
printf("\n\n");
system("pause");
return 0;
}
最终结果为: