堆排序
Profile
堆排序结合了插入排序(原地排序)和归并排序(时间复杂度)的优点。堆排序基于一种数据结构——堆。这里说的堆不是指JAVA虚拟机中存储对象的内存空间。堆分为最大堆、最小堆,不仅可以用来实现堆排序,更常见的是实现优先级队列,比如JAVA JDK中的PriorityQueue类就是以堆为数据结构基础实现的。这里暂且不写优先级队列的实现,实现成优先级队列,当然最好是写成一个类,就像JAVA JDK中的PriorityQueue一样。这里只写出堆排序的一个实现(基于最大堆)。
实现和注释
/**
* 堆排序
*/
inline int parent(int child) {
return (child - 1) / 2;
}
inline int left(int parent) {
return parent * 2 + 1;
}
inline int right(int parent) {
return parent * 2 + 2;
}
/**
* 保持最大堆的性质 初始条件:左子树left(i)、右子树right(i)
* 满足最大堆性质 调用之后保证,子树i也满足最大堆性质
*/
template <typename T>
void maxHeapify(vector<T>& A, int i, const int heapSize) {
while (true) {
int l = left(i);
int r = right(i);
int largest = i;// 默认父亲最大
if (l < heapSize && A[l] > A[i]) {
largest = l;// 左儿子较大
}
if (r < heapSize && A[r] > A[largest]) {
largest = r;// 右儿子较大
}
if (largest == i) {// 最大的就是父亲,则已经满足最大堆性质
break;
}
std::swap(A[i], A[largest]);// 交换父亲和最大值
i = largest;// 移动父亲的下标,向下移动
}
}
/**
* 自底向上建立最大堆 时间复杂度O(n)
*/
template <typename T>
void buildMaxHeap(vector<T>& A, const int heapSize) {
for (int i = heapSize >> 1; i >= 0; --i) {
maxHeapify(A, i, heapSize);
}
}
/**
* 堆排序
*/
template <typename T>
void heapSort(vector<T>& A) {
int heapSize = A.size();
buildMaxHeap(A, heapSize);
for (int i = heapSize - 1; i >= 1; --i) {
std::swap(A[0], A[i]);
--heapSize;
maxHeapify(A, 0, heapSize);
}
}