歸並排序的遞歸和非遞歸實現(C代碼)


遞歸實現(函數遞歸調用) --自頂向下

 1 /**
 2  * Merge_Sort: 歸並排序的遞歸實現
 3  * 注:算法導論上給出的合並排序算法
 4  * 遞歸過程是將待排序集合一分為二,
 5  * 直至排序集合就剩下一個元素為止,然后不斷的合並兩個排好序的數組
 6  * T(n) = O(nlgn)
 7 **/
 8 #include <stdio.h>
 9 #define LEN 8
10 
11 // 合並
12 void merge(int a[], int start, int mid, int end)
13 {
14     int n1 = mid - start + 1;
15     int n2 = end - mid;
16     int left[n1], right[n2];
17     int i, j, k;
18 
19     for (i = 0; i < n1; i++) /* left holds a[start..mid] */
20         left[i] = a[start+i];
21     for (j = 0; j < n2; j++) /* right holds a[mid+1..end] */
22         right[j] = a[mid+1+j];
23 
24     i = j = 0;
25     k = start;
26     while (i < n1 && j < n2)
27         if (left[i] < right[j])
28             a[k++] = left[i++];
29         else
30             a[k++] = right[j++];
31 
32     while (i < n1) /* left[] is not exhausted */
33         a[k++] = left[i++];
34     while (j < n2) /* right[] is not exhausted */
35         a[k++] = right[j++];
36 }
37 
38 // merge_sort():先排序,再合並
39 void merge_sort(int a[], int start, int end)
40 {
41     int mid;
42     if (start < end)
43     {
44         mid = (start + end) / 2;
45         printf("sort (%d-%d, %d-%d) %d %d %d %d %d %d %d %d\n",
46                start, mid, mid+1, end,
47                a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]);
48 
49         // 分解 + 解決:Divide + Conquer
50         merge_sort(a, start, mid); // 遞歸划分原數組左半邊array[start...mid]
51         merge_sort(a, mid+1, end); // 遞歸划分array[mid+1...end]
52         // 合並:Combine
53         merge(a, start, mid, end); // 合並
54 
55         printf("merge (%d-%d, %d-%d) to %d %d %d %d %d %d %d %d\n",
56                start, mid, mid+1, end,
57                a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]);
58     }
59 }
60 
61 int main(void)
62 {
63     int a[LEN] = { 5, 2, 4, 7, 1, 3, 2, 6 };
64     merge_sort(a, 0, LEN-1);
65 
66     return 0;
67 }

 

 

非遞歸(迭代,循環展開)--自底向上

 1 /**
 2  * merge_sort: 非遞歸實現 --迭代
 3  * 非遞歸思想: 將數組中的相鄰元素兩兩配對。用merge函數將他們排序,
 4  * 構成n/2組長度為2的排序好的子數組段,然后再將他們排序成長度為4的子數組段,
 5  * 如此繼續下去,直至整個數組排好序。
 6 **/
 7 
 8 #include <stdio.h>
 9 #include <stdlib.h>
10 #define LEN 8
11 
12 // merge_sort(): 非遞歸實現-自底向上
13 // 將原數組划分為left[min...max] 和 right[min...max]兩部分
14 void merge_sort(int *list, int length)
15 {
16     int i, left_min, left_max, right_min, right_max, next;
17     int *tmp = (int*)malloc(sizeof(int) * length);
18 
19     if (tmp == NULL)
20     {
21         fputs("Error: out of memory\n", stderr);
22         abort();
23     }
24 
25     for (i = 1; i < length; i *= 2) // i為步長,1,2,4,8……
26     {
27         for (left_min = 0; left_min < length - i; left_min = right_max)
28         {
29             right_min = left_max = left_min + i;
30             right_max = left_max + i;
31 
32             if (right_max > length)
33                 right_max = length;
34 
35             next = 0;
36             while (left_min < left_max && right_min < right_max)
37                 tmp[next++] = list[left_min] > list[right_min] ? list[right_min++] : list[left_min++];
38 
39             while (left_min < left_max)
40                 list[--right_min] = list[--left_max];
41 
42             while (next > 0)
43                 list[--right_min] = tmp[--next];
44         }
45     }
46 
47     free(tmp);
48 
49 }
50 
51 
52 int main(void)
53 {
54     int a[LEN] = { 5, 2, 4, 7, 1, 3, 2, 6 };
55     merge_sort(a, LEN);
56 
57     // print array
58     int i;
59     for (i = 0; i < LEN; i++)
60         printf("%d ", a[i]);
61 
62     return 0;
63 }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM