排序算法之 Heap Sort

Heap Sort (cpp_heap_sort.cc)
================================================================================
最好时间复杂度  O(nlogn)
平均时间复杂度  O(nlogn)
最坏时间复杂度  O(nlogn)
空间复杂度    O(1)
是否稳定     否

  Heap Sort利用的是二叉堆结构能在O(logn)时间内取出最大元素的特点,将所有元素构建成堆后依次取出完成排序。
  经典的取出最大元素的算法是将最后一个元素放到根的位置然后向下调整,由于调整后的位置理论上还是接近堆底,所以这种方法的复杂度接近O(2logn),在测试中我使用了一个改进算法,首先向上调整填充空出的根位置,在堆底留出空位,再将最后一个元素放入空位向上调整。这个改进算法减少了复杂度因子,在很大程度上提高了算法效率。
  Heap Sort是高级排序算法中能保证O(nlogn)时间界的和O(1)空间界的少数算法之一(还有两个是Inplace Merge Sort和堆排序的改进版Smooth Sort),在理论上是一个相当完美的算法。但由于堆排序所需比较次数较多,而且在比较、交换元素的时候也是大范围跳跃的,所以速度并不是很快。 

 1 #include <cstdio>
2 #include <cstdlib>
3 #include <ctime>
4
5 static unsigned int set_times = 0;
6 static unsigned int cmp_times = 0;
7
8 template<typename item_type> void setval(item_type& item1, item_type& item2) {
9 set_times += 1;
10 item1 = item2;
11 return;
12 }
13
14 template<typename item_type> int compare(item_type& item1, item_type& item2) {
15 cmp_times += 1;
16 return item1 < item2;
17 }
18
19 template<typename item_type> void swap(item_type& item1, item_type& item2) {
20 item_type item3;
21
22 setval(item3, item1);
23 setval(item1, item2);
24 setval(item2, item3);
25 return;
26 }
27
28 template<typename item_type> void heap_sort(item_type* array, int size) {
29 item_type tempitem;
30 int current;
31 int next;
32 int top = size / 2;
33
34 while(size > 0) {
35 if(top > 0) top -= 1; else swap(array[--size], array[0]);
36
37 setval(tempitem, array[top]);
38 current = top;
39 while(1) {
40 next = current * 2 + 1;
41 if(next + 1 < size && compare(array[next], array[next + 1])) {
42 next += 1;
43 }
44 if(next < size) {
45 setval(array[current], array[next]);
46 current = next;
47 } else break;
48 }
49
50 while(next > 0) {
51 next = (current - 1) / 2;
52 if(next >= top && compare(array[next], tempitem)) {
53 setval(array[current], array[next]);
54 current = next;
55 } else break;
56 }
57 setval(array[current], tempitem);
58 }
59 return;
60 }
61
62 int main(int argc, char** argv) {
63 int capacity = 0;
64 int size = 0;
65 int i;
66 clock_t clock1;
67 clock_t clock2;
68 double data;
69 double* array = NULL;
70
71 // generate randomized test case
72 while(scanf("%lf", &data) == 1) {
73 if(size == capacity) {
74 capacity = (size + 1) * 2;
75 array = (double*)realloc(array, capacity * sizeof(double));
76 }
77 array[size++] = data;
78 }
79
80 // sort
81 clock1 = clock();
82 heap_sort(array, size);
83 clock2 = clock();
84
85 // output test result
86 fprintf(stderr, "heap_sort:\t");
87 fprintf(stderr, "time %.2lf\t", (double)(clock2 - clock1) / CLOCKS_PER_SEC);
88 fprintf(stderr, "cmp_per_elem %.2lf\t", (double)cmp_times / size);
89 fprintf(stderr, "set_per_elem %.2lf\n", (double)set_times / size);
90 for(i = 0; i < size; i++) {
91 fprintf(stdout, "%lf\n", array[i]);
92 }
93 free(array);
94 return 0;
95 }

原文地址:https://www.cnblogs.com/richselian/p/2179146.html