HeapSort 堆排序
小根堆。
堆排序的时间,主要由建立初始堆和反复重建堆这两部分的时间开销构成,它们均是通过调用Heapify实现的。
建堆时,从除去叶子节点的n/2开始,调整堆的时间复杂度为O(logN)。
n-1次把堆顶元素与当前最后一个交换,然后调整堆。
总时间还是O(N*logN)
堆排序的最坏时间复杂度为O(N*logN)。堆排序的平均性能较接近于最坏性能。
由于建初始堆所需的比较次数较多,所以堆排序不适宜于记录数较少的文件。
堆排序是就地排序,辅助空间为O(1),
它是不稳定的排序方法。
来源:
http://student.zjzk.cn/course_ware/data_structure/web/paixu/paixu8.4.2.3.htm
#include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <climits> #include <cstdio> using namespace std; int N, a[100]; //从i节点开始调整,n为节点总数, 从0开始计算, i节点子节点为2*i+1, 2*i+2 //小根堆 void Heapify(int* a, int i, int n) { int j = 2*i+1, tmp = a[i]; while(j < n) { if(j+1<n && a[j+1]<a[j])//找左右孩子中最小的 ++j; if(a[j] >= tmp) break; a[i] = a[j]; i = j; j = 2*i+1; } a[i] = tmp; } void BuildHeap(int* a, int n) { for(int i = n/2-1; i >= 0; --i) { Heapify(a, i, n); } } void HeapSort(int* a, int n) { BuildHeap(a, n); for(int i = n-1; i >= 1; --i) { swap(a[i], a[0]); Heapify(a, 0, i); } } int main() { int a[100]; scanf("%d", &N); for(int i = 0; i < N; ++i) scanf("%d", a+i); HeapSort(a, N); for(int i = 0; i < N; ++i) printf("%d ", a[i]); puts(""); return 0; }
下面是大根堆呢~
#include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> using namespace std; int a[100], N; void Debug() { for(int i = 0; i < N; ++i) printf("%d ", a[i]); puts(""); } void Heapify(int* a, int i, int n) { int j = 2*i+1, tmp = a[i]; while(j < n) { if(j+1<n && a[j+1]>a[j]) ++j; if(a[j] < tmp) break; a[i] = a[j]; i = j; j = 2*i+1; } a[i] = tmp; } void BuildHeap(int* a, int n) { for(int i = n/2-1; i >= 0; --i) { Heapify(a, i, n); //printf("i=%d:", i); //Debug(); } } void HeapSort(int* a, int n) { BuildHeap(a, n); for(int i = n-1; i > 0; --i) { swap(a[0], a[i]); Heapify(a, 0, i); } } int main() { scanf("%d", &N); for(int i = 0; i < N; ++i) scanf("%d", a+i); Debug(); HeapSort(a, N); Debug(); return 0; }