本博客的代碼的思想和圖片參考:好大學慕課浙江大學陳越老師、何欽銘老師的《數據結構》算法
排序shell
1.函數的名稱規範編程
void X_Sort ( ElementType A[], int N )數組
2.大多數狀況下,爲簡單起見,討論從小大的整數排序數據結構
3.N是正整數app
4只討論基於比較的排序( >= < 有定義 )ide
5.只討論內部排序函數
6穩定性:任意兩個相等的數據,排序先後的相對位置不發生改變工具
7.沒有一種排序是任何狀況下都表現最好的oop
第一趟:比較第一個元素和第二元素,若是第一個元素比第二個元素大,就交換位置,不然就不交換位置;在比較第二元素和第三個元素的大小,若是第二個元素比第三個元素大,交換位置,不然不交換位置;而後接着比較第三個元素和第四個元素…… 直到比較到第N-1個元素和第N個元素。這樣一趟下來,能夠肯定最大的元素在N位置
第二趟:比較第一個元素和第二元素,若是第一個元素比第二個元素大,就交換位置,不然就不交換位置;在比較第二元素和第三個元素的大小,若是第二個元素比第三個元素大,交換位置,不然不交換位置;而後接着比較第三個元素和第四個元素……,直到比較到N-2 和N-1個元素。這樣,第二趟下面,第二大的元素能夠肯定在N-1位置。
第三趟……
…
這樣到第N趟,就能夠吧數組排序完成。
/*
* A method to implement bubble sort.If the bubble sort has no any swap
* operation at one time,indicating the array has been ordered.So we use a
* tag to make it effective
*@param a A integer array need to sort
*@param n The length of the array
*/
voidbubble_sort(elementType a[], int n) {
int i, j, flag;
for (i = n - 1; i >= 0; i--) {
flag = 0;
for (j = 0; j < i; j++) {
if (a[j] > a[j + 1]) {
swap(&a[j], &a[j + 1]);
flag = 1;
}
}
if (flag == 0) {
break;
}
}
}
最好的狀況:若是這個數組自己就是有序的,那麼時間複雜:T=O(N)
最壞的狀況:若是這個數組自己就是逆序的,那麼時間複雜度爲T=O(N^2)
由於只有當前面的元素嚴格的大於後面元素時,纔會交換位置,相對位置不會發生改變,那麼該算法是穩定的。
選擇排序的前提是保證數組中已有元素是有序的。例如在給數組的第i個元素排序(找合適位置)時,已經保證前面i-1個元素是有序的。
第一趟:當給數組中第一個元素排序時,由於就一個元素,默認就是有序的。
第二趟:當給數組中第二元素排序時,比較(前一個元素)第一個元素是否比他大,若是大,把前一個元素日後面摞一位,而後。
第三趟:給數組中第三個元素排序時,比較前一個元素是否是比他大,比他大,前一個元素向後摞一位。在比較在前面一個元素是否比他大,若是比他大,在吧在前一個元素日後摞一位;若是不比他大,那麼剛纔那個摞的那個空位就就放入該元素。
第四趟……
…
第N趟
/*
* Implemet insertion sort.
*@param a A integer array need to sort
*@param n The length of the array
*/
voidinsertion_sort(elementType a[], int n) {
int i, j;
elementType temp;
for (i = 1; i < n; i++) {
temp = a[i];
for (j = i; j > 0 && a[j - 1] > temp; j--) {
a[j] = a[j - 1];
}
a[j] = temp;
}
}
最好的狀況:若是這個數組自己就是有序的,那麼時間複雜:T=O(N)
最壞的狀況:若是這個數組自己就是逆序的,那麼時間複雜度爲T=O(N^2)
由於只有當前面的元素嚴格的大於後面元素時,纔會交換位置,相對位置不會發生改變,那麼該算法是穩定的。
爲了說明這個問題,我先給出一個例題:
給定初始序列{34, 8, 64, 51,32, 21},冒泡排序和插入排序分別須要多少次元素交換才能完成?
答:冒泡須要9次,選擇排序也須要9次。這是一個巧合嗎?
對於下標i<j,若是A[i]>A[j],則稱(i,j)是一對逆序對(inversion)
問題:序列{34, 8, 64, 51, 32, 21}中有多少逆序對?
(34, 8) (34, 32) (34, 21) (64, 51) (64, 32) (64, 21) (51, 32) (51, 21) (32, 21)
有九個逆序對。
交換兩個相鄰的逆序對正好消去一個逆序對!
插入排序(冒泡排序)的時間複雜度能夠從新定義爲:
T(N,I)=O(N,I).I爲N個元素中逆序對的個數
——若是須要排序的序列基本有序,則插入排序簡單且高效
定理:任意N個不一樣元素組成的序列平均具備N ( N - 1 ) / 4 個逆序對。
定理:任何僅以交換相鄰兩元素來排序的算
法,其平均時間複雜度爲 ( N^2 ) 。
這意味着:要提升算法效率,咱們必須
1.每次消去不止1個逆序對!
2. 每次交換相隔較遠的2個元素!
定義增量序列 D M > D M-1 > ... > D 1 = 1
對每一個 D k 進行「D k -間隔」排序 ( k = M, M-1, ... 1 )
注意:「D k -間隔」有序的序列,在執行「D k-1 -間隔」排序後,仍然是「D k -
間隔」有序的。下面用一幅圖片來講明希爾排序的過程
/*
* Implement base shell sort
*@param a A integer array need to sort
*@param n The length of the array
*/
voidshell_sort_base(elementType a[], int n) {
int i, j, d;
elementType temp;
for (d = n / 2; d > 0; d = d / 2) {
for (i = d; i < n; i++) {
temp = a[i];
for (j = i; j >= d && a[j - d] > temp; j -= d) {
a[j] = a[j - d];
}
a[j] = temp;
}
}
}
在基本的希爾排序中,咱們的間隔取 n/2 n/4 n/8 … n/2^i … 1
在上面基本的希爾排序中,最壞的時間複雜度T(n)=O(n^2).很糟糕
下面舉一個最壞狀況的例子
在介紹堆排序以前,咱們先介紹一下選擇排序。
選擇排序的算法思想:第一次從N個元素中選擇一個最小的。放入0位置,第二次從N個元素中選擇第二小的,放入1位置。… 第i次從N個元素選擇第i小的元素放入第i-1位置
下面是選擇排序的僞代碼描述
void Selection_Sort ( ElementType A[], int N )
{
for ( i = 0; i < N; i ++ ) {
MinPosition = ScanForMin( A, i, N–1 );
/* 從A[i]到A[N–1]中找最小元,並將其位置賦給MinPosition */
Swap( A[i], A[MinPosition] );
/* 將未排序部分的最小元換到有序部分的最後位置 */
}
}
對於交換元素的操做,是線性。問題在於從N個元素每次找到最i小的元素。選擇排序比較暴力,他每次都是從N個元素中選擇最小的元素,而後進行交換位置。這樣時間時間複雜度T(N)=O(N^2).咱們若是改進找到最小元的操做?
答案是使用咱們之前學過的工具,最小堆。
算法思想:把用戶給定的數組調整成一個最小堆,每次從堆中彈出一個最小的元素,使用臨時數組保存,而後在吧臨時數組的元素複製回原數組。
僞代碼描述:
void Heap_Sort ( ElementType A[], int N )
{
BuildHeap(A); /* O(N) */
for ( i=0; i<N; i++ )
TmpA[i] = DeleteMin(A); /* O(logN) */
for ( i=0; i<N; i++ ) /* O(N) */
A[i] = TmpA[i];
}
經過僞代碼咱們能夠看到,此算法的時間複雜的度爲T(N)=O(NlogN),可是他須要開闢一個臨時的數組O(N)來存放已經排序好的元素。並且還修養話費元素複製的時間。
算法思想:首先吧數組調整成最大堆。把最大堆的第一個元素和最後一個元素調換位置。這樣最大的元素就在原數組的最後。而後吧剩下n-1個元素調整成最大堆。重複上面的操做。這樣每次選出最大的元素。
僞代碼描述:
void Heap_Sort ( ElementType A[], int N )
{
for ( i=N/2-1; i>=0; i-- )/* BuildHeap */
PercDown( A, i, N );
for ( i=N-1; i>0; i-- ) {
Swap( &A[0], &A[i] ); /* DeleteMax */
PercDown( A, 0, i );
}
}
1.定理:堆排序處理N個不一樣元素的隨機排列的平均比較次數是2N logN - O(Nlog logN) 。
2.雖然堆排序給出最佳平均時間複雜度,但實際效果不如用Sedgewick增量序列的希爾排序。
3.堆排序好處是取出前i個最小的數。
在介紹歸併排序的算法以前,咱們先來介紹一下「有序子列的歸併」下面經過一張圖片來介紹
下面是給出有序子列歸併的源代碼
/*
* Merge sub-sequence to original array.
* @param a original <code>elementType</code> array to store the elements
* @param tmpA temporary <code>elementType</code> array to store the temporary elements
* @param l The start index of left sub-sequence
* @param r The start index of left sub-sequence
* @param rightEnd The end index of left sub-sequence
*/
voidmerge(elementType a[], elementType tmpA[], int l, int r, int rightEnd) {
/*
* lefeEnd is the r-1,the sub-sequence is adjacent
*/
int leftEnd = r - 1;
/*
* tmp is the counter of the <code>tmpA</code>
* we should let <code>tmpA</code> index corresponding original array
*/
int tmp = l;
/*
* Record the quantity of the all elements
*/
int numElements = rightEnd - l + 1;
int i;
while (l <= leftEnd && r <= rightEnd) {
if (a[l] <= a[r]) {
tmpA[tmp++] = a[l++];
} else {
tmpA[tmp++] = a[r++];
}
}
while (l <= leftEnd) {
tmpA[tmp++] = a[l++];
}
while (r < rightEnd) {
tmpA[tmp++] = a[r++];
}
/*
* Put <code>tmpA</code> elements into the original array
*/
for (i = 0; i < numElements; i++, rightEnd--) {
a[rightEnd] = tmpA[rightEnd];
}
}
這個代碼的時間複雜度在上面已經說過了,爲T(N)=O(N)
這個時間複雜的沒有最好,最壞,平均。不論什麼樣的序列,都是NlogN的時間複雜度。
在歸併排序中,咱們使用到一個臨時數組,那麼這個臨時數組在哪裏分配比較合理?
設想一下,若是咱們在merge函數中申請,那會怎麼樣呢。那就會出現,沒調用一次merge函數,咱們須要申請和釋放這樣的一個臨時數組。這樣申請釋放的操做以下圖所示:
這樣會平凡的對內存進行申請和釋放,是很不划算的,並且最後仍是要申請一個和N同樣大學的數組,那麼咱們還不如本身在接口函數中把她直接定義好。以下圖所示:
雖然咱們在一開始歸併過程當中只會用到臨時數組的一小部分,可是總比每次申請釋放來的划算。
咱們知道遞歸算法是很消耗系統的堆棧,並且很容易形成內存的溢出。因此咱們下面咱們使用非遞歸的方法來實現歸併排序。
非遞歸算法的思想是一開始對數組兩兩進行歸併,而後對兩個元素組成的集合在進行兩兩歸併。最後完成數組的排序。下面使用圖片來講明
/*
* Use loop method to implement the merge sort
* @param a A integer array need to sort
* @param n The length of the array
*/
voidmerger_SortLoop(elementType a[], int n) {
int length;
elementType *tmpA;
length = 1;
tmpA = malloc(n * sizeof(elementType));
if (tmpA != NULL) {
while (length < n) {
/*
* merge ordered sub-sequence into <code>tmpA</code>
*/
mergerPass(a, tmpA, n, length);
length *= 2;
/*
* merge ordered sub-sequence from <code>tmpA</code> into <code>a</code>
*/
mergerPass(tmpA, a, n, length);
length *= 2;
}
free(tmpA);
} else {
printf("no enough to apply for temporary array");
}
}
給定N個(長整型範圍內的)整數,要求輸出從小到大排序後的結果。
本題旨在測試各類不一樣的排序算法在各類數據狀況下的表現。各組測試數據特色以下:
數據1:只有1個元素;
數據2:11個不相同的整數,測試基本正確性;
數據3:103個隨機整數;
數據4:104個隨機整數;
數據5:105個隨機整數;
數據6:105個順序整數;
數據7:105個逆序整數;
數據8:105個基本有序的整數;
數據9:105個隨機正整數,每一個數字不超過1000。
輸入第一行給出正整數N(≤105),隨後一行給出N個(長整型範圍內的)整數,其間以空格分隔。
在一行中輸出從小到大排序後的結果,數字間以1個空格分隔,行末不得有多餘空格。
114 981 10 -17 0 -20 29 50 8 43 -5
-20 -17 -5 0 4 8 10 29 43 50 98
可是希爾排序也有經過的例子
從上面的測試結果來看,堆排序,歸併排序都完美經過了測試,並且效率挺高的。
冒泡排序沒有經過測試很正常,由於時間複雜度爲O(N^2).
是我感到詫異的是,插入排序竟然經過了測試,雖然挺耗時,可是希爾排序在測試點7:105個逆序整數居然沒有經過。個人希爾排序使用Sedgewick序列。不是理論上是O(N^(4/3)),怎麼會沒有經過呢。可是時間複雜度和冒泡排序相近的插入排序竟然經過了。好奇怪。並且插入排序在測試點7:105個逆序整數所有是逆序數最壞的時間複雜度爲O(N^2),怎麼就經過了呢。好奇怪。後來屢次對希爾排序進行測試,發現有時候能夠經過,有時候沒有經過,估計是受機器的影響。感受希爾排序效率不高,平均的都在5000ms以上
1 /* 2 * bubbleSort.c 3 * 4 * Created on: 2017年5月18日 5 * Author: ygh 6 */ 7 8 #include <stdio.h> 9 10 typedef int elementType; 11 #define MAX_LENGTH 100000 12 13 /* 14 * Swap two integer number value 15 */ 16 void swap(elementType *a, elementType *b) { 17 int temp = *b; 18 *b = *a; 19 *a = temp; 20 } 21 /* 22 * A method to implement bubble sort.If the bubble sort has no any swap 23 * operation at one time,indicating the array has been ordered.So we use a 24 * tag to make it effective 25 *@param a A integer array need to sort 26 *@param n The length of the array 27 */ 28 void bubble_sort(elementType a[], int n) { 29 int i, j, flag; 30 for (i = n - 1; i >= 0; i--) { 31 flag = 0; 32 for (j = 0; j < i; j++) { 33 if (a[j] > a[j + 1]) { 34 swap(&a[j], &a[j + 1]); 35 flag = 1; 36 } 37 } 38 if (flag == 0) { 39 break; 40 } 41 } 42 } 43 44 /* 45 * Print the array to console 46 * @param a A integer array need to sort 47 * @param n The length of the array 48 */ 49 void printArray(int a[], int n) { 50 int i; 51 for (i = 0; i < n; i++) { 52 if (i == n - 1) { 53 printf("%d", a[i]); 54 } else { 55 printf("%d ", a[i]); 56 } 57 } 58 printf("\n"); 59 } 60 61 /* 62 * Get input data from command 63 */ 64 void getInputData(elementType *a, int n) { 65 int i; 66 elementType x; 67 for (i = 0; i < n; i++) { 68 scanf("%d", &x); 69 a[i] = x; 70 } 71 } 72 73 int main() { 74 int a[MAX_LENGTH]; 75 int n; 76 scanf("%d", &n); 77 getInputData(a, n); 78 bubble_sort(a, n); 79 printArray(a, n); 80 return 0; 81 }
1 /* 2 * insertionSort.c 3 * 4 * Created on: 2017年5月18日 5 * Author: ygh 6 */ 7 8 #include <stdio.h> 9 10 #define MAX_LENGTH 100000 11 typedef int elementType; 12 13 /* 14 * Swap two integer number value 15 */ 16 void swap(elementType *a, elementType *b) { 17 int temp = *b; 18 *b = *a; 19 *a = temp; 20 } 21 /* 22 * Implement insertion sort. 23 *@param a A integer array need to sort 24 *@param n The length of the array 25 */ 26 void insertion_sort(elementType a[], int n) { 27 int i, j; 28 elementType temp; 29 for (i = 1; i < n; i++) { 30 temp = a[i]; 31 for (j = i; j > 0 && a[j - 1] > temp; j--) { 32 a[j] = a[j - 1]; 33 } 34 a[j] = temp; 35 } 36 37 } 38 39 /* 40 * Print the array to console 41 * @param a A integer array need to sort 42 * @param n The length of the array 43 */ 44 void printArray(int a[], int n) { 45 int i; 46 for (i = 0; i < n; i++) { 47 if (i == n - 1) { 48 printf("%d", a[i]); 49 } else { 50 printf("%d ", a[i]); 51 } 52 } 53 printf("\n"); 54 } 55 56 /* 57 * Get input data from command 58 */ 59 void getInputData(elementType *a, int n) { 60 int i; 61 elementType x; 62 for (i = 0; i < n; i++) { 63 scanf("%d", &x); 64 a[i] = x; 65 } 66 } 67 68 int main() { 69 int a[MAX_LENGTH]; 70 int n; 71 scanf("%d", &n); 72 getInputData(a, n); 73 insertion_sort(a, n); 74 printArray(a, n); 75 return 0; 76 }
1 /* 2 * shellSort.c 3 * 4 * Created on: 2017年5月18日 5 * Author: ygh 6 */ 7 8 #include <stdio.h> 9 #include <math.h> 10 11 #define MAX_LENGTH 100000 12 typedef int elementType; 13 14 /* 15 * Swap two integer number value 16 */ 17 void swap(elementType *a, elementType *b) { 18 int temp = *b; 19 *b = *a; 20 *a = temp; 21 } 22 23 int getSedgewickStep(int *step, int n) { 24 int i, v1, v2, counter = 0; 25 i = 0; 26 for (i = 0; i < n; i++) { 27 v1 = 9 * pow(4, i) - 9 * pow(2, i) + 1; 28 if (v1 > 0 && v1 < n) { 29 step[counter++] = v1; 30 } 31 v2 = pow(4, i) - 3 * pow(2, i) + 1; 32 if (v2 > 0 && v2 < n) { 33 step[counter++] = v2; 34 } 35 if (v1 > n && v2 > n) { 36 break; 37 } 38 } 39 return counter; 40 } 41 42 /* 43 * A method to implement bubble sort.If the bubble sort has no any swap 44 * operation at one time,indicating the array has been ordered.So we use a 45 * tag to make it effective 46 *@param a A integer array need to sort 47 *@param n The length of the array 48 */ 49 void bubble_sort(int a[], int n) { 50 int i, j, flag; 51 for (i = n - 1; i >= 0; i--) { 52 flag = 0; 53 for (j = 0; j < i; j++) { 54 if (a[j] > a[j + 1]) { 55 swap(&a[j], &a[j + 1]); 56 flag = 1; 57 } 58 } 59 if (flag == 0) { 60 break; 61 } 62 } 63 } 64 65 /* 66 * Implement base shell sort 67 *@param a A integer array need to sort 68 *@param n The length of the array 69 */ 70 void shell_sort_expand_Sedgewick(elementType a[], int n) { 71 int i, j, d, counter, step; 72 elementType temp; 73 int sequence[] = { 1, 5, 19, 41, 109, 209, 505, 929, 2161, 3905, 8929, 74 16001, 6289, 64769 }; 75 counter = 13; 76 /*int sequence[n / 2]; 77 counter = getSedgewickStep(sequence, n); 78 bubble_sort(sequence, counter);*/ 79 /*printArray(sequence, counter); 80 return;*/ 81 for (d = 0; d < counter && sequence[d] < n; d++) { 82 step = sequence[d]; 83 for (i = step; i < n; i++) { 84 temp = a[i]; 85 for (j = i; j >= step && a[j - step] > temp; j -= step) { 86 a[j] = a[j - step]; 87 } 88 a[j] = temp; 89 } 90 } 91 92 } 93 94 /* 95 * Implement base shell sort 96 *@param a A integer array need to sort 97 *@param n The length of the array 98 */ 99 void shell_sort_expand_Sedgewick2(elementType a[], int n) { 100 int i, j, d, counter, step; 101 elementType temp; 102 int sequence[n / 2]; 103 counter = getSedgewickStep(sequence, n); 104 bubble_sort(sequence, counter); 105 for (d = 0; d < counter && sequence[d] < n; d++) { 106 step = sequence[d]; 107 for (i = step; i < n; i++) { 108 temp = a[i]; 109 for (j = i; j >= step && a[j - step] > temp; j -= step) { 110 a[j] = a[j - step]; 111 } 112 a[j] = temp; 113 } 114 } 115 116 } 117 118 /* 119 * Implement base shell sort 120 *@param a A integer array need to sort 121 *@param n The length of the array 122 */ 123 void shell_sort_base(elementType a[], int n) { 124 int i, j, d; 125 elementType temp; 126 for (d = n / 2; d > 0; d = d / 2) { 127 for (i = d; i < n; i++) { 128 temp = a[i]; 129 for (j = i; j >= d && a[j - d] > temp; j -= d) { 130 a[j] = a[j - d]; 131 } 132 a[j] = temp; 133 } 134 } 135 136 } 137 138 /* 139 * Print the array to console 140 * @param a A integer array need to sort 141 * @param n The length of the array 142 */ 143 void printArray(int a[], int n) { 144 int i; 145 for (i = 0; i < n; i++) { 146 if (i == n - 1) { 147 printf("%d", a[i]); 148 } else { 149 printf("%d ", a[i]); 150 } 151 } 152 printf("\n"); 153 } 154 155 /* 156 * Get input data from command 157 */ 158 void getInputData(elementType *a, int n) { 159 int i; 160 elementType x; 161 for (i = 0; i < n; i++) { 162 scanf("%d", &x); 163 a[i] = x; 164 } 165 } 166 167 int main() { 168 int a[MAX_LENGTH]; 169 int n; 170 scanf("%d", &n); 171 getInputData(a, n); 172 shell_sort_expand_Sedgewick2(a, n); 173 printArray(a, n); 174 return 0; 175 }
1 /* 2 * heapSort.c 3 * 4 * Created on: 2017年5月18日 5 * Author: ygh 6 */ 7 8 #include <stdio.h> 9 10 #define MAX_LENGTH 100000 11 typedef int elementType; 12 13 /* 14 * Swap two integer number value 15 */ 16 void swap(elementType *a, elementType *b) { 17 int temp = *b; 18 *b = *a; 19 *a = temp; 20 } 21 22 /* 23 * Update the element of tree make the tree to be a maximal heap 24 * @param a A <code>elementType</code> array to store the elements 25 * @param p The index of the element need to update 26 * @param n The length of the array 27 */ 28 void percDowm(elementType a[], int p, int n) { 29 int parent, child; 30 elementType x; 31 x = a[p]; 32 for (parent = p; (parent * 2 + 1) < n; parent = child) { 33 child = parent * 2 + 1; 34 if ((child != n - 1) && a[child] < a[child + 1]) { 35 child++; 36 } 37 if (x >= a[child]) { 38 break; 39 } else { 40 a[parent] = a[child]; 41 } 42 } 43 a[parent] = x; 44 } 45 46 /* 47 * Implement heap sort 48 * @param a A integer array need to sort 49 * @param n The length of the array 50 */ 51 void heap_sort(elementType a[], int n) { 52 int i; 53 /* 54 * Build max heap 55 */ 56 for (i = n / 2 - 1; i >= 0; i--) { 57 percDowm(a, i, n); 58 } 59 60 /* 61 * Swap and update heap 62 */ 63 for (i = n - 1; i > 0; i--) { 64 swap(&a[0], &a[i]); 65 percDowm(a, 0, i); 66 } 67 } 68 69 /* 70 * Print the array to console 71 * @param a A integer array need to sort 72 * @param n The length of the array 73 */ 74 void printArray(int a[], int n) { 75 int i; 76 for (i = 0; i < n; i++) { 77 if (i == n - 1) { 78 printf("%d", a[i]); 79 } else { 80 printf("%d ", a[i]); 81 } 82 } 83 printf("\n"); 84 } 85 86 /* 87 * Get input data from command 88 */ 89 void getInputData(elementType *a, int n) { 90 int i; 91 elementType x; 92 for (i = 0; i < n; i++) { 93 scanf("%d", &x); 94 a[i] = x; 95 } 96 } 97 98 int main() { 99 int a[MAX_LENGTH]; 100 int n; 101 scanf("%d", &n); 102 getInputData(a, n); 103 heap_sort(a, n); 104 printArray(a, n); 105 return 0; 106 }
1 /* 2 * mergeSort.c 3 * 4 * Created on: 2017年5月18日 5 * Author: ygh 6 */ 7 8 #include <stdio.h> 9 #include <stdlib.h> 10 #define MAX_LENGTH 100000 11 12 typedef int elementType; 13 14 /* 15 * Swap two integer number value 16 */ 17 void swap(elementType *a, elementType *b) { 18 int temp = *b; 19 *b = *a; 20 *a = temp; 21 } 22 23 /* 24 * Merge sub-sequence to original array. 25 * @param a original <code>elementType</code> array to store the elements 26 * @param tmpA temporary <code>elementType</code> array to store the temporary elements 27 * @param l The start index of left sub-sequence 28 * @param r The start index of left sub-sequence 29 * @param rightEnd The end index of left sub-sequence 30 */ 31 void merge(elementType a[], elementType tmpA[], int l, int r, int rightEnd) { 32 /* 33 * lefeEnd is the r-1,the sub-sequence is adjacent 34 */ 35 int leftEnd = r - 1; 36 /* 37 * tmp is the counter of the <code>tmpA</code> 38 * we should let <code>tmpA</code> index corresponding original array 39 */ 40 int tmp = l; 41 /* 42 * Record the quantity of the all elements 43 */ 44 int numElements = rightEnd - l + 1; 45 int i; 46 while (l <= leftEnd && r <= rightEnd) { 47 if (a[l] <= a[r]) { 48 tmpA[tmp++] = a[l++]; 49 } else { 50 tmpA[tmp++] = a[r++]; 51 } 52 } 53 while (l <= leftEnd) { 54 tmpA[tmp++] = a[l++]; 55 } 56 while (r <= rightEnd) { 57 tmpA[tmp++] = a[r++]; 58 } 59 60 /* 61 * Put <code>tmpA</code> elements into the original array 62 */ 63 for (i = 0; i < numElements; i++, rightEnd--) { 64 a[rightEnd] = tmpA[rightEnd]; 65 } 66 } 67 68 /* 69 * Implement the merge sort 70 * @param a original <code>elementType</code> array to store the elements 71 * @param tmpA temporary <code>elementType</code> array to store the temporary elements 72 * @param l The start index of the array which need to sort 73 * @param rightEnd The end index of the array which need to sort 74 */ 75 void mergetSortRecursive(elementType a[], elementType tmpA[], int l, 76 int rightEnd) { 77 int center; 78 if (l < rightEnd) { 79 center = (l + rightEnd) / 2; 80 mergetSortRecursive(a, tmpA, l, center); 81 mergetSortRecursive(a, tmpA, center + 1, rightEnd); 82 merge(a, tmpA, l, center + 1, rightEnd); 83 } 84 } 85 86 /* 87 * Implement merge sort 88 * @param a A integer array need to sort 89 * @param n The length of the array 90 */ 91 void merger_sortRecursive(elementType a[], int n) { 92 elementType *tmpA; 93 tmpA = malloc(n * sizeof(elementType)); 94 if (tmpA != NULL) { 95 mergetSortRecursive(a, tmpA, 0, n - 1); 96 free(tmpA); 97 } else { 98 printf("no enough space to apply for temporary array"); 99 } 100 } 101 102 /* 103 *merge ordered sub-sequence 104 * @param a original <code>elementType</code> array to store the elements 105 * @param tmpA temporary <code>elementType</code> array to store the temporary elements 106 * @param n The length of the a 107 * @param the ordered current sub-sequence length 108 */ 109 void mergerPass(elementType a[], elementType tmpA[], int n, int lenth) { 110 int i, j; 111 /* 112 * The loop will stop when meet the last two ordered sub-sequence 113 * The rest may be two sub-sequence of one sub-sequence 114 */ 115 for (i = 0; i <= n - 2 * lenth; i += lenth * 2) { 116 merge(a, tmpA, i, i + lenth, i + 2 * lenth - 1); 117 } 118 /* 119 *If the rest of is two sub-sequence 120 */ 121 if (i + lenth < n) { 122 merge(a, tmpA, i, i + lenth, n - 1); 123 } else { 124 for (j = i; j < n; j++) 125 tmpA[j] = a[j]; 126 } 127 } 128 129 /* 130 * Use loop method to implement the merge sort 131 * @param a A integer array need to sort 132 * @param n The length of the array 133 */ 134 void merger_SortLoop(elementType a[], int n) { 135 int length; 136 elementType *tmpA; 137 length = 1; 138 tmpA = malloc(n * sizeof(elementType)); 139 if (tmpA != NULL) { 140 while (length < n) { 141 /* 142 * merge ordered sub-sequence into <code>tmpA</code> 143 */ 144 mergerPass(a, tmpA, n, length); 145 length *= 2; 146 /* 147 * merge ordered sub-sequence from <code>tmpA</code> into <code>a</code> 148 */ 149 mergerPass(tmpA, a, n, length); 150 length *= 2; 151 } 152 free(tmpA); 153 } else { 154 printf("no enough to apply for temporary array"); 155 } 156 } 157 158 /* 159 * Print the array to console 160 * @param a A integer array need to sort 161 * @param n The length of the array 162 */ 163 void printArray(int a[], int n) { 164 int i; 165 for (i = 0; i < n; i++) { 166 if (i == n - 1) { 167 printf("%d", a[i]); 168 } else { 169 printf("%d ", a[i]); 170 } 171 } 172 printf("\n"); 173 } 174 175 /* 176 * Get input data from command 177 */ 178 void getInputData(elementType *a, int n) { 179 int i; 180 elementType x; 181 for (i = 0; i < n; i++) { 182 scanf("%d", &x); 183 a[i] = x; 184 } 185 } 186 187 int main() { 188 int a[MAX_LENGTH]; 189 int n; 190 scanf("%d", &n); 191 getInputData(a, n); 192 // merger_sortRecursive(a, n); 193 merger_SortLoop(a, n); 194 printArray(a, n); 195 return 0; 196 }
辛苦一天,數據結構課程的編程練習總算是進入了前100名。付出是值得的