堆排序
堆排序是一种高效的比较排序算法,运行时间为O(nlgn)。
这种排序需要用到一种叫做(二叉)堆的数据结构,堆是一种数组对象,也可以看做一颗完全二叉树,对于任一节点,左右子节点和父节点分别可如下简单算出
PARENT(i) ((i - 1) / 2)
LEFT(i) (2 * i + 1)
RIGHT(i) (2 * i + 2)
堆分为大根堆和小根堆,分别具有如下性质:
a[PARENT(i)] >= a[i]
a[PARENT(i)] <= a[i]
本文采用大根堆说明堆排序算法的实现。
c++实现源代码如下:
#include <iostream> using namespace std; #include <algorithm> #define LEFT(i) (2 * i + 1) #define RIGHT(i) (2 * i + 2) void _max_heapify(int *a, int i, int length) { int l = LEFT(i); int r = RIGHT(i); int largest = 0; if (l < length && a[l] > a[i]) { largest = l; } else { largest = i; } if (r < length && a[r] > a[largest]) { largest = r; } if (largest != i) { swap(a[largest], a[i]); _max_heapify(a, largest, length); } } void _built_heap(int *a, int length) { for (int i = length / 2; i >= 0; --i) { _max_heapify(a, i, length); } } void heap_sort(int *a, int length) { _built_heap(a, length); int i = length - 1; while (i >= 1) { swap(a[0], a[length - 1]); length -= 1; _max_heapify(a, 0, length); --i; } } void print(int *a, int length) { for (int i = 0; i < length; ++i) { cout << a[i] << endl; } } int main() { int a[10] = {1, 3, 2, 4, 6, 5, 7, 8, 9, 0}; heap_sort(a, 10); print(a, 10); }首先说明_max_heapify函数,这个函数用来保持大根堆的性质,对于给定的以下标为i节点为根的堆是大根堆,如果子节点大于i节点,则两子节点中最大的节点与i节点互换,若两子树依然如此,则递归调用此函数,注意:调用此函数时假设两子树分别为大根堆。
_built_heap函数用来建堆,因为对于length/2以后的元素都是叶子节点,可以看做单节点的大根堆,所以可以对其他节点分别调用_max_heapify函数完成整个堆的建立。为了满足_max_heapify函数的调用规则,应在数组中从后向前遍历。
heap_sort函数用来实现堆排序,因为每次建堆后第一个元素即是数组中的最大元素,所以将它放到最后即可,然后对其余元素继续此过程,直至数组剩余两个元素为止,至此排序完成。