C++排序演算法——歸併排序
阿新 • • 發佈:2018-12-10
歸併排序C++
歸併排序從小到大排序:首先讓陣列中的每一個數單獨成為長度為1的區間, 然後兩兩一組有序合併,得到長度為2的有序區間,依次進行,直到合成整個區間。
#include <iostream> using namespace std; //4 歸併排序 /* 歸併排序從小到大排序:首先讓陣列中的每一個數單獨成為長度為1的區間, 然後兩兩一組有序合併,得到長度為2的有序區間,依次進行,直到合成整個區間。 */ //4.3 核心程式碼(函式) //1 遞迴實現 //函式宣告 void MergeSort(int array[]); void MSort(int array[], int Result[], int start, int end); void Merge(int array[], int Ans[], int start, int midd, int endd); //將兩個排序序列排序 從小到大排序 //函式實現 void MergeSort(int array[]) { MSort(array, array, 0, 9); } void Merge(int array[],int Ans[], int start, int midd, int endd) //將兩個排序序列排序 從小到大排序 { int i = start; //記錄前半段的下標 int j ; //記錄後半段的下標 int k; //記錄結果Ans的下標 for ( j = midd + 1, k = i; i <= midd && j <= endd; k++) { if (array[i] > array[j]) { Ans[k] = array[j]; j++; } else { Ans[k] = array[i]; i++; } } if (i <= midd) // { for (; i <= midd; i++,k++) { Ans[k] = array[i]; } } if (j <= endd) // { for (; j <= endd; j++, k++) { Ans[k] = array[j]; } } } void MSort(int array[], int Result[], int start, int end) { int Tmp[1000]; if (start == end) Result[start] = array[start]; else { int mid = (start+end) / 2; //中間點的位置,從中間點將陣列分成兩部分 MSort(array, Tmp, start, mid); //左半部分排序 MSort(array, Tmp, mid + 1, end); //右半部分排序 Merge(Tmp, Result,start, mid, end); //合併 } } //2:迭代實現 void MergeSortIter(int k[], int n) { int i, next, left_min, left_max, right_min, right_max; //動態申請一個與原來陣列一樣大小的空間用來儲存 int *temp = (int *)malloc(n * sizeof(int)); //逐級上升,第一次比較2個,第二次比較4個,第三次比較8個。。。 for (i = 1; i<n; i *= 2) { //每次都從0開始,陣列的頭元素開始 for (left_min = 0; left_min<n - i; left_min = right_max) { right_min = left_max = left_min + i; right_max = left_max + i; //右邊的下標最大值只能為n if (right_max>n) { right_max = n; } //next是用來標誌temp陣列下標的,由於每次資料都有返回到K, //故每次開始得重新置零 next = 0; //如果左邊的資料還沒達到分割線且右邊的陣列沒到達分割線,開始迴圈 while (left_min<left_max&&right_min<right_max) { if (k[left_min] < k[right_min]) { temp[next++] = k[left_min++]; } else { temp[next++] = k[right_min++]; } } //上面迴圈結束的條件有兩個,如果是左邊的遊標尚未到達,那麼需要把 //陣列接回去,可能會有疑問,那如果右邊的沒到達呢,其實模擬一下就可以 //知道,如果右邊沒到達,那麼說明右邊的資料比較大,這時也就不用移動位置了 while (left_min < left_max) { //如果left_min小於left_max,說明現在左邊的資料比較大 //直接把它們接到陣列的min之前就行 k[--right_min] = k[--left_max]; } while (next>0) { //把排好序的那部分陣列返回該k k[--right_min] = temp[--next]; } } } } //非遞迴的方法,避免了遞迴時深度為log2N的棧空間, //空間只是用到歸併臨時申請的跟原來陣列一樣大小的空間,並且在時間效能上也有一定的提升, //因此,使用歸併排序是,儘量考慮用非遞迴的方法。 int main( ) { int array[10] = { 3,5,4,6,9,8,7,1,2,0}; int len = sizeof(array) / sizeof(int); for (int i = 0; i < len; i++) cout << array[i] << " "; cout << endl; cout << "*************************"<< endl; //insertSort(array,len); //插入排序 MergeSort(array); //歸併排序 //adjust_quicksort(array,10); //快速排序 for (int i = 0; i < len; i++) cout << array[i] << " "; cout << endl; system("pause"); return 0; }