大原则:
排升序用大堆
排降序用小堆
基本思想:将待排序的序列构造一个大堆。此时,整个序列的最大值就是堆根的根节点。将它移走(与堆数组的末元素交换,此时末元素就是最大值,即就是在数组的最后一个位置)。然后将剩余的n-1个序列重新构造成一个堆,这样就会得到n个元素的次大值。如此反复,便能得到一个有序序列了。
源码:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<math.h>
void Swanp(int* x, int* y)
{
int a = *x;
*x = *y;
*y = a;
}
void HeapAdjust(int* heap, int n, int x)
{
int LeftSon = 2 * x + 1;
int RightSon = 2 * x + 2;
if (LeftSon <= n - 1)
{
int MaxSon = LeftSon;
if (RightSon <= n - 1 && heap[LeftSon] < heap[RightSon])
MaxSon = RightSon;
if (heap[x] < heap[MaxSon])
{
Swanp(&heap[x], &heap[MaxSon]);
HeapAdjust(heap, n, MaxSon);
}
}
}
//排升序 建大堆
void HeapCreate(int* heap, int n)
{
//下滤法
int deep=1;
//确定深度 找最右边的一个叶子或 (满二叉树)的话找倒数第二层最右边的第一个
while (1)
{
int min = pow(2, deep - 1) - 1;
int max = pow(2, deep) - 1;
if (min < n && max >= n)
break;
deep++;
}
int ace = pow(2, deep - 1) - 2; //下滤的起始位置
while (ace >= 0)
{
int LeftSon = 2 * ace + 1;
int RightSon = 2 * ace + 2;
if (LeftSon <= n - 1)
{
int MaxSon = LeftSon;
if (RightSon <= n - 1 && heap[LeftSon] < heap[RightSon])
MaxSon = RightSon;
if (heap[ace] < heap[MaxSon])
{
Swanp(&heap[ace], &heap[MaxSon]);
HeapAdjust(heap,n,MaxSon);
}
}
ace--;
}
}
void HeapSort(int* heap, int n)
{
HeapCreate(heap, n);
int i = n;
while (i--)
{
Swanp(&heap[0], &heap[i]);
HeapAdjust(heap,i, 0);
}
}
解释一下:建堆过程中
ace找的就是倒数第二行的最右边的一个 采用下滤的方法 将最大值替换上来
本人画图水平有限 ,这个照片里面的图 很生动的描述了这一个过程。
这么下滤调整一遍 大堆就建好了。
堆建好了 下面就简单了 根节点替换最后一个 然后在进行调整
递归调整就好,就看有没有 左儿子 右儿子 进行比较一下
递归结束条件就是,双亲节点不和儿子节点互换了。
测试一下: