#include <stdio.h>
#pragma warning(disable:4996)
先简述一下堆的性质:
1.堆中某个节点的值总是不大于或不小于其父节点的值
2.堆总是一棵完全二叉树
//堆的实现
//向下调整算法 前提:当前树的左右子树都是堆(大堆或者小堆),才能调整
//此例为小堆
void Adjust(int *a, int n, int root)
{
int parent = root;
int child = 2 * parent + 1;
while (child < n)
{
//当右孩子存在,并且右孩子小于左孩子
//child++到右孩子
if (child + 1 < n&&a[child+1] < a[child])
{
child++;
}
//如果父亲大于孩子,则孩子与父亲进行交换!
if (a[parent] >a[child])
{
int temp = a[parent];
a[parent] = a[child];
a[child] = temp;
parent = child;
child = parent * 2 + 1;
}
else{
break;
}
}
}
int main()
{
//堆的创建
//下面我们给出一个数组,这个数组逻辑上可以看做一个完全二叉树,
//但是还不是一个堆。
int a[] = {
27,15,19,18,28,34,65,49,25,37};
int n = sizeof(a) / sizeof(a[0]);
//我们通过从根节点开始的向下调整法,调整成一个堆(大堆或者小堆)
Adjust(a, n, 0);
int i = 0;
for (; i < n; i++)
{
printf("%d ", a[i]);
}
printf("\n\n\n");
return 0;
}
//此例为小堆
void Adjust(int *a, int n, int root)
{
int parent = root;
int child = 2 * parent + 1;
while (child < n)
{
//当右孩子存在,并且右孩子小于左孩子
//child++到右孩子
if (child + 1 < n&&a[child+1] < a[child])
{
child++;
}
//如果父亲大于孩子,则孩子与父亲进行交换!
if (a[parent] >a[child])
{
int temp = a[parent];
a[parent] = a[child];
a[child] = temp;
parent = child;
child = parent * 2 + 1;
}
else{
break;
}
}
}
//堆排序--->此例为降序
void HeapSort(int *a, int n)
{
//建堆
//当用堆进行降序的时候,需要建一个小堆,反之则是大堆
//当树的左右子树不满足小堆时,从第一个非叶节点开始进行建堆,
//最后建成一个小堆
for (int i=(n-1-1)/2; i>=0; i--)
{
Adjust(a, n,i);
//建堆的时间复杂度为O(N)
}
//每次选出剩下数中的最小值,从后往前放
//时间复杂度为0(N*logN)
int end = n - 1;
while (end > 0)
{
int tmp = a[end];
a[end] = a[0];
a[0] = tmp;
Adjust(a, end, 0);
//选出次小的数
end--;
}
}
int main()
{
int a[] = {
27, 28, 65, 25, 15, 34, 19, 49, 18, 37 };
int n = sizeof(a) / sizeof(a[0]);
//堆排序
HeapSort(a, n);
int i = 0;
for (; i < n; i++)
{
printf("%d ", a[i]);
}
printf("\n\n\n");
return 0;
}