这篇文章主要介绍堆排序算法。
关于选择排序、插入排序、冒泡排序、希尔排序的详解可参见:常规排序算法Java详解
关于快速排序的详解可参见:快速排序算法Java详解
关于归并排序的详解可参见:归并排序算法Java详解
关于基数排序的详解可参见:基数排序算法Java详解
1. 堆的定义
如果一颗完全二叉树每个节点的关键字都大于或等于子节点中的关键字,那么该树就成为大顶堆;如果一颗完全二叉树每个节点的关键字都小于或等于子节点中的关键字,那么该树就成为小顶堆;大顶堆和小顶堆统称为堆。
如下图中,左边的树是大顶堆,右边的树是小顶堆。堆一定是完全二叉树。
2. 堆排序的Java语言实现
堆排序的定义为:在输出堆顶元素后,使得剩余n-1个元素的序列重新建成一个堆,然后再次输出堆顶元素,依次类推,便能得到一个有序序列。
堆排序需要解决两个问题:第一,如何由一个无序序列建成一个堆?第二,如何在输出堆顶元素后调整剩余元素成为一个新堆。
2.1 建堆和堆调整过程
建堆的Java语言实现如下:
private void heapAdjust(int[] items, int s, int n) {
int j, rc = items[s];
for(j=2*s+1; j<n; j*=2) {
if(j < n - 1 && items[j] < items[j+1]) j++;
if(rc > items[j]) break;
items[s] = items[j]; s = j;
}
items[s] = rc;
}
2.2 堆排序过程
堆排序的Java语言实现如下:
//堆排序
public void heapSort(int[] items) {
int t, i;
for(i=items.length/2-1; i>=0; i--)
heapAdjust(items, i, items.length);//创建大顶堆
for(i=items.length-1; i>0; i--) {
t = items[0]; items[0] = items[i]; items[i] = t; //交换
heapAdjust(items, 0, i-1);
}
}
3. 堆排序的C语言实现
上面是用Java语言实现的堆排序过程。下面列出堆排序的C语言实现,该实现与Java语言的实现是一样的,具体如下:
void heapAdjust(int *a, int s, int n) {
int j, rc = a[s];
for(j=2*s+1; j<n; j*=2) {
if(j < n - 1 && a[j] < a[j+1]) j++;
if(rc > a[j]) break;
a[s] = a[j]; s = j;
}
a[s] = rc;
}
void heapSort(int *a) {
int t, i;
for(i=N/2-1; i>=0; i--) heapAdjust(a, i, N);//创建大顶堆
for(i=N-1; i>0; i--) {
t = a[0]; a[0] = a[i]; a[i] = t;
heapAdjust(a, 0, i-1);
}
}
堆排序在最坏的情况下的时间复杂度也为O(N*logN),这是堆排序最大的优点。此外,堆排序仅仅需要一个记录大小供交换用的辅助空间。
全文完。转载请注明出处。
参考文献
1. 严蔚敏,数据结构(C语言版),清华大学出版社.
2.Robert Sedgewick,算法:C语言实现,机械工业出版社.