Non-recursive Merge Sort (cpp_merge_sort.cc)
================================================================================
最好时间复杂度 O(nlogn)
平均时间复杂度 O(nlogn)
最坏时间复杂度 O(nlogn)
空间复杂度 O(n)
是否稳定 是
Non-recursive Merge Sort是归并排序的非递归(自底向上归并)实现,将序列视为长度为s的有序序列集合(初始时s=1),然后将有序序列两两进行Merge操作,得到长度为2s的有序序列集合,重复操作直到序列中只剩下一个有序序列时排序结束。
Non-recursive Merge Sort在所有测试的算法中速度仅次于Quick Sort,在需要排序稳定性或者O(nlogn)最坏情况时是Quick Sort的一个很好的替代,但所需O(n)的空间复杂度是对算法速度和适用范围一个严重的制约。SGI-STL库中std::stable_sort()的内部实现就是Non-recursive Merge 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 ncmerge_sort(item_type* array, int size) {
29 int step_width;
30 int ins_pos;
31 int l;
32 int m;
33 int r;
34 int pos1;
35 int pos2;
36 item_type* temp_array = new item_type[size];
37
38 for(step_width = 2; step_width < size * 2; step_width *= 2) {
39 for(l = 0; l + step_width / 2 < size; l += step_width) {
40 m = l + step_width / 2;
41 r = m + step_width / 2 < size ? m + step_width / 2 : size;
42
43 pos1 = l;
44 pos2 = m;
45 ins_pos = 0;
46 while(pos1 < m && pos2 < r) {
47 if(compare(array[pos2], array[pos1])) {
48 setval(temp_array[ins_pos++], array[pos2++]);
49 } else {
50 setval(temp_array[ins_pos++], array[pos1++]);
51 }
52 }
53 while(pos1 < m) setval(temp_array[ins_pos++], array[pos1++]);
54 while(pos2 < r) setval(temp_array[ins_pos++], array[pos2++]);
55 while(ins_pos > 0) {
56 setval(array[--r], temp_array[--ins_pos]);
57 }
58 }
59 }
60 delete[] temp_array;
61 return;
62 }
63
64 int main(int argc, char** argv) {
65 int capacity = 0;
66 int size = 0;
67 int i;
68 clock_t clock1;
69 clock_t clock2;
70 double data;
71 double* array = NULL;
72
73 // generate randomized test case
74 while(scanf("%lf", &data) == 1) {
75 if(size == capacity) {
76 capacity = (size + 1) * 2;
77 array = (double*)realloc(array, capacity * sizeof(double));
78 }
79 array[size++] = data;
80 }
81
82 // sort
83 clock1 = clock();
84 ncmerge_sort(array, size);
85 clock2 = clock();
86
87 // output test result
88 fprintf(stderr, "ncmerge_sort:\t");
89 fprintf(stderr, "time %.2lf\t", (double)(clock2 - clock1) / CLOCKS_PER_SEC);
90 fprintf(stderr, "cmp_per_elem %.2lf\t", (double)cmp_times / size);
91 fprintf(stderr, "set_per_elem %.2lf\n", (double)set_times / size);
92 for(i = 0; i < size; i++) {
93 fprintf(stdout, "%lf\n", array[i]);
94 }
95 free(array);
96 return 0;
97 }