排序算法之 Smooth Sort

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

  Smooth Sort基本思想和Heap Sort相同,但Smooth Sort使用的是一种由多个堆组成的优先队列,这种优先队列在取出最大元素后剩余元素可以就地调整成优先队列,所以Smooth Sort不用像Heap Sort那样反向地构建堆,在数据基本有序时可以达到O(n)复杂度。Smooth Sort算法在维基百科上有详细介绍。
  Smooth 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 static const unsigned int leonardo[] = {
29 1, 1, 3, 5, 9, 15, 25, 41, 67, 109, 177, 287, 465, 753, 1219, 1973,
30 3193, 5167, 8361, 13529, 21891, 35421, 57313, 92735, 150049, 242785,
31 392835, 635621, 1028457, 1664079, 2692537, 4356617, 7049155, 11405773,
32 18454929, 29860703, 48315633, 78176337, 126491971, 204668309, 331160281,
33 535828591, 866988873, 1402817465, 2269806339u, 3672623805u,
34 };
35
36 template<typename item_type> inline void smooth_sort_fix(
37 item_type* array, int current_heap, int level_index, int* levels) {
38 int prev_heap;
39 int max_child;
40 int child_heap1;
41 int child_heap2;
42 int current_level;
43
44 while(level_index > 0) {
45 prev_heap = current_heap - leonardo[levels[level_index]];
46 if(compare(array[current_heap], array[prev_heap])) {
47 if(levels[level_index] > 1) {
48 child_heap1 = current_heap - 1 - leonardo[levels[level_index] - 2];
49 child_heap2 = current_heap - 1;
50 if(compare(array[prev_heap], array[child_heap1])) break;
51 if(compare(array[prev_heap], array[child_heap2])) break;
52 }
53 swap(array[current_heap], array[prev_heap]);
54 current_heap = prev_heap;
55 level_index -= 1;
56 } else break;
57 }
58
59 current_level = levels[level_index];
60 while(current_level > 1) {
61 max_child = current_heap;
62 child_heap1 = current_heap - 1 - leonardo[current_level - 2];
63 child_heap2 = current_heap - 1;
64
65 if(compare(array[max_child], array[child_heap1])) max_child = child_heap1;
66 if(compare(array[max_child], array[child_heap2])) max_child = child_heap2;
67 if(max_child == child_heap1) {
68 swap(array[current_heap], array[child_heap1]);
69 current_heap = child_heap1;
70 current_level -= 1;
71 }
72 else if(max_child == child_heap2) {
73 swap(array[current_heap], array[child_heap2]);
74 current_heap = child_heap2;
75 current_level -= 2;
76 } else break;
77 }
78 return;
79 }
80
81 template<typename item_type> void smooth_sort(item_type* array, int size) {
82
83 int levels[64] = {1};
84 int toplevel = 0;
85 int i;
86
87 for(i = 1; i < size; i++) {
88 if(toplevel > 0 && levels[toplevel - 1] - levels[toplevel] == 1) {
89 toplevel -= 1;
90 levels[toplevel] += 1;
91 } else if(levels[toplevel] != 1) {
92 toplevel += 1;
93 levels[toplevel] = 1;
94 } else {
95 toplevel += 1;
96 levels[toplevel] = 0;
97 }
98 smooth_sort_fix(array, i, toplevel, levels);
99 }
100
101 for(i = size - 2; i > 0; i--) {
102 if(levels[toplevel] <= 1) {
103 toplevel -= 1;
104 } else {
105 levels[toplevel] -= 1;
106 levels[toplevel + 1] = levels[toplevel] - 1;
107 toplevel += 1;
108
109 smooth_sort_fix(array, i - leonardo[levels[toplevel]], toplevel - 1, levels);
110 smooth_sort_fix(array, i, toplevel, levels);
111 }
112 }
113 return;
114 }
115
116 int main(int argc, char** argv) {
117 int capacity = 0;
118 int size = 0;
119 int i;
120 clock_t clock1;
121 clock_t clock2;
122 double data;
123 double* array = NULL;
124
125 // generate randomized test case
126 while(scanf("%lf", &data) == 1) {
127 if(size == capacity) {
128 capacity = (size + 1) * 2;
129 array = (double*)realloc(array, capacity * sizeof(double));
130 }
131 array[size++] = data;
132 }
133
134 // sort
135 clock1 = clock();
136 smooth_sort(array, size);
137 clock2 = clock();
138
139 // output test result
140 fprintf(stderr, "smooth_sort:\t");
141 fprintf(stderr, "time %.2lf\t", (double)(clock2 - clock1) / CLOCKS_PER_SEC);
142 fprintf(stderr, "cmp_per_elem %.2lf\t", (double)cmp_times / size);
143 fprintf(stderr, "set_per_elem %.2lf\n", (double)set_times / size);
144 for(i = 0; i < size; i++) {
145 fprintf(stdout, "%lf\n", array[i]);
146 }
147 free(array);
148 return 0;
149 }

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