torch的下載及安裝
通過一張圖瞭解什麼是歸併排序
歸併排序實際上運用了“分”和“治”的思想。怎樣理解“分”和“治”?
分:就是將一個大的陣列逐漸分解為多個最大長度不超過2的陣列。
治:就是將這些小的陣列依次合併排序,最後變成一個最大長度且有序的陣列。
通過上面的歸併排序的圖解能夠很自然的想到要實現這個排序需要用到遞迴。
首先講怎樣進行"分"的操作:
1 void mergeSort(int *nums,int low,int high){ 2 int mid = (low+high)/2; 3 if(low<high) {4 mergeSort(nums,low,mid); 5 mergeSort(nums,mid+1,high); 6 merge(nums,low,mid,high);//關於"治"的函式 7 } 8 }
怎樣理解這段程式碼?為了便於敘述,建立陣列
7 | 2 | 5 | 3 |
執行上面的mergeSort函式:
1.第一次呼叫該方法,初始資料為:
1 nums[4] = {7,2,5,3}; 2 low = 0; 3 high = 3;
2.得到mid=(0+3)/2= 1;由於low<high,所以有
1 mergeSort(nums,low,mid); //此時的low=0,mid=1。令此函式為A2 mergeSort(nums,mid+1,high);//此時的miid+1=2,high=3。令此函式為B 3 merge(nums,low,mid,high);
3.執行函式A,得到mid=(0+1)/2=0;由於low<high,所以有
1 mergeSort(nums,low,mid); //此時的low=0,mid=0。令此函式為C 2 mergeSort(nums,mid+1,high);//此時的miid+1=1,high=1。令此函式為D 3 merge(nums,low,mid,high);//令此函式為E
4.執行函式C,得到mid=(0+0)/2=0;由於low=high,所以函式C執行完畢,返回到步驟3執行函式D。
5.執行函式D,得到mid=(1+1)/2=1;由於low=high,所以函式D執行完畢,返回到步驟3執行函式E(就到了"治"的階段)。
6.執行完步驟5,返回到步驟2執行函式B。
7.執行函式B,得到mid= (2+3)/2=2;由於low<high,所以有
1 mergeSort(nums,low,mid);// 此時的low=2,mid=2。令此函式為F 2 mergeSort(nums,mid+1,high);// 此時的miid+1=3,high=3。令此函式為G 3 merge(nums,low,mid,high);// 令此函式為H
8.執行函式F,得到mid=(2+2)/2=2;由於low=high,所以函式F執行完畢,返回到步驟7執行函式G。
9.執行函式G,得到mid=(3+3)/2=3;由於low=high,所以函式G執行完畢,返回步驟7執行函式H("治")。
10.執行完函式G,返回步驟2執行函式merge。
再講怎樣進行"治"的操作:
1 void merge(int *nums,int low,int mid,int high) { 2 int copyArray[numsSize],flag,i,j,q;//numsSize為陣列的長度 3 for(q = 0;q<numsSize;q++) {//將原陣列複製到新陣列 4 copyArray[q] = nums[q]; 5 } 6 for(i = low,j = mid+1,flag=low;i<=mid && j<=high;) { 7 if(copyArray[j]<copyArray[i]){ 8 nums[flag++] = copyArray[j++]; 9 }else { 10 nums[flag++] = copyArray[i++]; 11 } 12 } 13 while(i<=mid) { 14 nums[flag++] = copyArray[i++]; 15 } 16 while(j<=high) { 17 nums[flag++] = copyArray[j++]; 18 } 19 }
在執行mergeSort函式的過程中,步驟5第一次執行了merge函式。這裡著重對第一次執行merge函式做一個詳細的解釋。
初始資料
1 nums[4] = {7,2,5,3}; 2 copyArray[4] = {7,2,5,3}; 3 low = 0; 4 mid = 1; 5 high = 1;
執行迴圈
1 for(i = low,j = mid+1,flag=low;i<=mid && j<=high;) { 2 if(copyArray[j]<copyArray[i]){ 3 nums[flag++] = copyArray[j++]; 4 }else { 5 nums[flag++] = copyArray[i++]; 6 } 7 }
初始i、j、flag的值為
1 i = 0; 2 j = 1; 3 flag = 0;
因為
1 copyArray[0]>copyArray[1]//copyArray[0]=7 copyArray[1] = 2
所以有
1 nums[0] = 2; 2 flag++ = 1;//右邊的值是flag++以後的值 3 j++ = 2;
因為
1 high = 1; 2 j = 2;
不滿足迴圈條件
1 j<=high
故for迴圈終止。接著執行
1 while(i<=mid) { 2 nums[flag++] = copyArray[i++]; 3 } 4 while(j<=high) { 5 nums[flag++] = copyArray[j++]; 6 }
由於i<=mid,故執行第一個while迴圈
1 nums[1] = 7 //copyArray[0] = 7 2 i++ = 1;
因為i>mid,迴圈結束,merge函式呼叫結束。此時的陣列變成
1 nums[4] = {2,7,5,3};
第二次和第三次merge函式呼叫過程類似。