外部排序(歸並排序)
定義
基本思想及步驟
步驟
1.思想 一
2.思想 二
實現操作
1.二路歸並
1.1.c
遞歸
1 //二路一次歸並過程的算法 2 //low為本次二路歸並排序的第1有序區的第1個元素,i指向第1個元素, mid為第1有序區的最后1個元素 3 void merge(int List[], int low, int mid, int high) 4 { 5 //mid+1為第2有序區第1個元素,mid為第1有序區的最后1個元素 6 //i 指向第 1 有序區的第 1 個元素 7 int i = low; 8 //j 指向第 2 有序區的第 1 個元素,high 為第 2 有序區的最后一個元素 9 int j = mid + 1; 10 //temp數組暫存合並的有序序列 11 int *temp = new int[high - low + 1]; 12 //設置臨時數組的指示標志 k 13 int k = 0; 14 //內存分配失敗 15 if(!temp){ 16 cout<<"數組分配失敗!"; 17 exit(0); 18 } 19 //順序選取兩個有序區的較小元素,存儲到t數組中,因為是遞增排序 20 while(i <= mid && j <= high){ 21 //較小的元素,存入temp臨時數組中 22 if(List[i] <= List[j]){ 23 temp[k++] = List[i++]; 24 }else{ 25 temp[k++] = List[j++]; 26 } 27 }// end of while 28 //比完之后,假如第1個有序區仍有剩余,則直接全部復制到 temp 數組 29 while(i <= mid){ 30 temp[k++] = List[i++]; 31 } 32 //比完之后,假如第2個有序區還有剩余,則直接全部復制到 temp 數組 33 while(j <= high){ 34 temp[k++] = List[j++]; 35 } 36 //將排好序的序列,重存回到 list 中 low 到 high 區間 37 for(i = low, k = 0; i <= high; i++, k++){ 38 List[i] = temp[k]; 39 } 40 //delete [] 刪除動態數組的內存 41 delete []temp; 42 } 43 44 //遞歸實現二路歸並排序(也就是分治法的思想) 45 void mergeSort(int List[], int low, int high) 46 { 47 //二路歸並排序,分為二路 48 int mid = (low + high) / 2; 49 //終止條件,low >= high, 不是while,且不含等號,否則死循環 50 if(low < high) 51 { 52 //遞歸過程,二路歸並排序遞歸過程 53 mergeSort(List, low, mid); 54 mergeSort(List, mid + 1, high); 55 //歸並 56 merge(List, low, mid, high); 57 } 58 } 59 60 int main(void) 61 { 62 int source[7] = {49, 38, 65, 97, 76, 13, 27}; 63 64 mergeSort(source, 0, 6); 65 66 for (int i = 0; i < 7; i++) { 67 printf(" %d ", source[i]); 68 } 69 70 return 0; 71 }
非遞歸
1 //非遞歸算法實現二路歸並排序,length代表數組長度,即數組最大下標是 legth - 1 2 void mergeSort(int List[],int length) 3 { 4 //回憶圖解的過程,二路歸並算法的流程,不同於遞歸,遞歸是先遞歸語句,然后歸並函數,這樣歸並函數是倒序執行(和遞歸函數執行順序相反) 5 int size = 1; 6 int low; 7 int mid; 8 int high; 9 //size 是標記當前各個歸並序列的high-low,從1,2,4,8,……,2*size 10 while(size <= length - 1) 11 { 12 //從第一個元素開始掃描,low代表第一個分割的序列的第一個元素 13 low = 0; 14 //當前的歸並算法結束的條件 15 while(low + size <= length - 1) 16 { 17 //mid代表第一個分割的序列的最后一個元素 18 mid = low + size - 1; 19 //high 代表第二個分割的序列的最后一個元素 20 high = mid + size; 21 //判斷一下:如果第二個序列個數不足size個 22 if(high > length - 1){ 23 //調整 high 為最后一個元素的下標即可 24 high = length - 1; 25 } 26 //調用歸並函數,進行分割的序列的分段排序 27 merge(List, low, mid, high); 28 //打印出每次歸並的區間 29 cout << "low:" << low << " mid:" << mid << " high:" << high << endl; 30 //下一次歸並時第一序列的第一個元素位置 31 low = high + 1; 32 }// end of while 33 //范圍擴大一倍,二路歸並的過程 34 size *= 2; 35 }// end of while 36 }
1.2.c++
遞歸
非遞歸
1.3.python
遞歸
非遞歸
1 def mergeSort(arr): 2 import math 3 if(len(arr)<2): 4 return arr 5 middle = math.floor(len(arr)/2) 6 left, right = arr[0:middle], arr[middle:] 7 return merge(mergeSort(left), mergeSort(right)) 8 9 def merge(left,right): 10 result = [] 11 while left and right: 12 if left[0] <= right[0]: 13 result.append(left.pop(0)); 14 else: 15 result.append(right.pop(0)); 16 while left: 17 result.append(left.pop(0)); 18 while right: 19 result.append(right.pop(0)); 20 return result