堆排序是一种很优秀的算法,还可以利用堆实现优先队列!
特点:
1.最坏情况的时间复杂度: 上限 nlgn;(比插入排序快)
2.原址排序 (不同于归并排序)
步骤:
1.最大堆维护
2.建堆
3.堆排序(不断地从根取出元素,再调用维护函数保持堆性质)
//数组的第一个元素是指示堆中元素的数量,不包括a[0],所以数组总大小为 a[0]+1,就是元素个数n+1;
//调整最大堆
#define LEFT(i) (i << 1)
#define RIGHT(i) ((i << 1) + 1)
#define PARENT(i) (i >> 1)
void heap_adj(int a[], int i)
{
int large;
int left = LEFT(i);
int right = RIGHT(i);
if (left <= a[0] && a[left] > a[i])
large = left;
else
large = i;
if (right <= a[0] && a[right] > a[large])
large = right;
if (large != i)
{
exchange(a+i, a+large);
heap_adj(a, large);
}
}
void exchange(int *a, int *b)
{
int tmp;
tmp = *a;
*a = *b;
*b = tmp;
}
//建立最大堆, n/2+1,,,,,n 就是叶子了!
void build_max_heap(int a[])
{
int i;
for ( i = a[0]/2; i >=1; i--)
{
heap_adj(a,i);
}
}
//堆排序
void heap_sort(int a[])
{
int i;
int j = a[0];
i = a[0];
build_max_heap(a);
while (i >= 2)
{
exchange(a+1, a+i);
i--;
a[0]--;
heap_adj(a, 1);
}
a[0] = j;//因为上面减了,为了方便后面打印而做的动作,后面改进
}