日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C语言,谁都能看得懂的归并排序

發布時間:2023/12/20 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言,谁都能看得懂的归并排序 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

喜歡看排序算法動態效果的,可以看看這個網站

https://visualgo.net/zh/sorting

里面很多算法的動畫解釋,可以看到算法的排序效果,而且還附帶了偽代碼的實現過程。

本來想錄制幾張動圖放上來,但是因為圖片較大,傳不上來,公眾號對動態圖片有限制,喜歡的同學可以點擊我上面的鏈接,自己去嘗試一下。

我畫了一個圖片,用來表示歸并排序的運算過程

排序的過程

先把需要排序的數據分成兩份。

把兩份的數據依次進行排序并組合在一起。

再把排序后的兩組數據進行并入一起排序。

好了,寫代碼吧

我們先實現,「把兩份的數據依次進行排序并組合在一起

下面是實現這個的算法過程

/**?r[]?:?需要排序的數組*?s[]?:?排序后保存數據的數組*?left:?排序的起始位置*?mid?:?排序的中間位置*?right:排序的最右邊位置*/ int?merge(int?r[],int?s[],int?left,int?mid,int?right) {int?i,j,k;i=left;j=mid+1;k=left;for(;i?<=?mid?&&?j<=right;){if(r[i]<=r[j])s[k]?=?r[i++];elses[k]?=?r[j++];k++;}for(;i<=mid;)s[k++]=r[i++];for(;j<=right;)s[k++]=r[j++];return?0; }

如果我們對兩個數進行排序

經過上面的那個函數排序后,我們會把[3,1]排序成[1,3]。

——

那,如果我們需要對4個數字進行排序呢?

我們需要先把4個數字分成2組

然后,我們需要依次對上面的兩組數據進行排序,得到下面新的兩組數據

然后,我們需要把已經排序的兩個數組進行排序

s[]?是保存的排序結果,r[] 是需要排序的數組。

left,mid,right 是排序數組中的三個位置。

left = 0;

right = 3;

mid = ( left + right )/2 =?1;

進入函數體,我們需要三個變量來協助我們進行運算

i = left = 0;

j = mid +1 =?1 +1 = 2;

k = left = 0;

它們看起來是這樣子的

把r[i]?和 r[j]?兩個數進行比較,把小的那個數放到s[k] 里面,然后再移位

比較之后變成

然后再執行下面的代碼

for(;i?<=?mid?&&?j<=right;){if(r[i]<=r[j])s[k]?=?r[i++];elses[k]?=?r[j++];k++; }

這時候 j = 4

這時候就退出了 for 循環

退出for 循環后 就開始執行下面的 for 循環

?for(;i<=mid;)s[k++]=r[i++];for(;j<=right;)s[k++]=r[j++];

這樣后,會變成這樣

這樣就退出 merge 函數

經過上面的過程,我們需要應該有點悟性,我們需要使用遞歸來解決這些問題

可以看下面的文章了解啥是遞歸

C 語言,你真的懂遞歸了嗎?

然后呢,我們就寫了一個這樣的遞歸函數,放心吧,在學習樹的時候,也是需要這種遞歸操作的。

/**?r[]?:?需要排序的數組*?s[]?:?排序后保存數據的數組*?left:?排序的起始位置*?right:排序的最右邊位置*/ int?merge_sort(int?r[],int?s[],int?left,int?right) {int?mid;int?t[20];if(left==right)s[left]=r[right];else{mid=(left+right)/2;merge_sort(r,t,left,mid);/*sort?left~mid*/merge_sort(r,t,mid+1,right);/*sort?mid+1~right*/merge(t,s,left,mid,right);/*merge?sort?left,mid,right*/}return?0; }

這個函數就是遞歸函數,遞歸最后退出機制是?

left?==?right?

再然后,我們需要一個?main 函數

完整的代碼實現如下

#include?<stdio.h> #include?<stdlib.h>/**?r[]?:?需要排序的數組*?s[]?:?排序后保存數據的數組*?left:?排序的起始位置*?mid?:?排序的中間位置*?right:排序的最右邊位置*/ int?merge(int?r[],int?s[],int?left,int?mid,int?right) {int?i,j,k;i=left;j=mid+1;k=left;for(;i?<=?mid?&&?j<=right;){if(r[i]<=r[j])s[k]?=?r[i++];elses[k]?=?r[j++];k++;}for(;i<=mid;)s[k++]=r[i++];for(;j<=right;)s[k++]=r[j++];return?0; }/**?r[]?:?需要排序的數組*?s[]?:?排序后保存數據的數組*?left:?排序的起始位置*?right:排序的最右邊位置*/ int?merge_sort(int?r[],int?s[],int?left,int?right) {int?mid;int?t[20];if(left==right)s[left]=r[right];else{mid=(left+right)/2;merge_sort(r,t,left,mid);/*sort?left~mid*/merge_sort(r,t,mid+1,right);/*sort?mid+1~right*/merge(t,s,left,mid,right);/*merge?sort?left,mid,right*/}return?0; }int?main() {int?a[8]?=?{6,5,3,1,8,7,2,4};int?i;merge_sort(a,a,0,7);for(i=0;i<sizeof(a)/sizeof(a[0]);i++)printf("%d?",a[i]);printf("\n");return?0; }

程序輸出

1?2?3?4?5?6?7?8

算法復雜度,翻開以前寫的文章

時間復雜度和空間復雜度,一看就懂,面試前必過一遍

中間是?mid =?(left+right)/2?

可以猜到是 O(logN) ,也就是排序的時間是用logN時間去拆分的,而且拆分的時候,我們還需要進行排序,也就是代碼里面提到的,排序的時間是O(n),所以在拆分和排序中需要花費的時間是 O(NlogN)。

拆分需要花費 O(logN) ,那合并的時候自然也需要花費O(logN)

總的算法時間是

O(NlogN + logN)??=?O(NlogN)


推薦閱讀:

專輯|Linux文章匯總

專輯|程序人生

專輯|C語言

我的知識小密圈

關注公眾號,后臺回復「1024」獲取學習資料網盤鏈接。

歡迎點贊,關注,轉發,在看,您的每一次鼓勵,我都將銘記于心~

總結

以上是生活随笔為你收集整理的C语言,谁都能看得懂的归并排序的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。