堆排序
这里介绍了堆的操作 https://www.cnblogs.com/zuofaqi/p/9665619.html
堆还可以用来做堆排序,其过程是:对于从小到大的排序,使用最大堆。建堆之后,交换第一个元素和最后一个堆元素,这样,最后一个堆元素A[n-1]就是最大值,而A[0...n-2]的堆结构就被破坏了,通过堆顶元素的下沉操作,使A[0...n-2]再次成为一个堆。再交换第一个元素和最后一个堆元素,循环下去,最后,整个堆都是有序的。
void heapSort(int* arr, int heapsize)
{
// 建堆
adjust_by_sink(arr, heapsize);
while (heapsize > 1)
{
int tmp = arr[0];
arr[0] = arr[heapsize-1];
arr[heapsize-1] = tmp;
// 堆长减1, 新堆首元素下沉
heapsize--;
sink(arr, 0, heapsize);
}
}
通过这个过程,我们可以知道,堆排序是原址排序。同时,堆排序是不稳定排序,比如 [2,6,8,5,0,1,7,7]这个数组,在使用下沉法建堆的时候,两个7的相对位置就变了。堆排序时间复杂度是O(nlogn)
完整代码:
#include <stdio.h> #include <string.h> #include <stdlib.h> #define ARRLEN 100 #define LEFT(idx) (((idx)<<1)+1) #define RIGHT(idx) (((idx)<<1)+2) #define PARENT(idx) (((idx)-1)>>1) // 下沉 void sink(int* arr, int index, int heapsize) { // 左子树节点超出堆长度范围 if (LEFT(index) > heapsize-1) { return; } int maxidx = -1; // 右子树节点超出堆长度范围,或者左节点的值比右节点的值大 if (RIGHT(index) > heapsize-1 || (arr[LEFT(index)] > arr[RIGHT(index)])) { maxidx = LEFT(index); } else { maxidx = RIGHT(index); } if (maxidx != -1 && arr[maxidx] > arr[index]) { int tmp = arr[maxidx]; arr[maxidx] = arr[index]; arr[index] = tmp; sink(arr, maxidx, heapsize); } } // 上浮 void upward(int* arr, int index, int heapsize) { if (0 == index) { return; } if (arr[PARENT(index)] < arr[index]) { int tmp = arr[index]; arr[index] = arr[PARENT(index)]; arr[PARENT(index)] = tmp; upward(arr, PARENT(index), heapsize); } } void adjust_by_sink(int* arr, int heapsize) { // 下沉法,从最后一个非叶子节点开始,到根节点,依次执行下沉 for (int i = PARENT(heapsize-1); i >= 0; i--) { sink(arr, i, heapsize); } } void adjust_by_upward(int* arr, int heapsize) { // 上浮法,从根节点到最后一个节点,依次执行上浮 for (int i = 0; i < heapsize; i++) { upward(arr, i, heapsize); } } int insert(int* arr, int value, int& heapsize) { if (heapsize > ARRLEN) { return -1; } arr[heapsize] = value; upward(arr, heapsize, heapsize+1); heapsize++; return 0; } void del(int* arr, int& heapsize) { if (heapsize <= 0) { return; } arr[0] = arr[heapsize-1]; heapsize--; sink(arr, 0, heapsize); } void heapSort(int* arr, int heapsize) { // 建堆 adjust_by_sink(arr, heapsize); while (heapsize > 1) { int tmp = arr[0]; arr[0] = arr[heapsize-1]; arr[heapsize-1] = tmp; // 堆长减1, 新堆首元素下沉 heapsize--; sink(arr, 0, heapsize); } } int main() { int arr[ARRLEN] = {2,3,4,5,1,2,3,7}; int heapsize = 8; heapSort(arr, heapsize); for (int i = 0; i < heapsize; i++) { printf("%d\n", arr[i]); } return 0; }