C語(yǔ)言遞歸實(shí)現(xiàn)歸并排序詳解
歸并排序遞歸實(shí)現(xiàn)還是比較難理解的,感覺(jué)涉及遞歸一般理解起來(lái)都會(huì)比較有難度吧,但是看了b站視頻,然后照著打下來(lái),然后自己寫(xiě)了點(diǎn)注釋?zhuān)桶l(fā)現(xiàn)不知不覺(jué)都大概懂了。
這里的歸并講的是升序排序
歸并排序思路大概就是:先劃分?jǐn)?shù)組,將數(shù)組劃分為左右半?yún)^(qū),分成的左右半?yún)^(qū),各自再劃分左右半?yún)^(qū),一直劃分,直到最后左右半?yún)^(qū)的元素都為一個(gè)時(shí),開(kāi)始合并,因?yàn)槎紕澐譃橐粋€(gè)元素了,那么此時(shí)兩個(gè)元素的排序就非常簡(jiǎn)單了,只需要比較大小就可以排序了,那么回溯上去會(huì)發(fā)現(xiàn)每組都是兩兩有序了,那么直接再依次比較兩組之間的排頭元素即可,取較小的賦值給臨時(shí)數(shù)組,然后排頭元素就變成后一個(gè)元素,一直這么比較,直到兩組數(shù)據(jù)有一組為空時(shí),只需要將另一組不為空的接在臨時(shí)數(shù)組后面即可,因?yàn)榇藭r(shí)不為空的剩下的元素是有序的且都比此時(shí)有序的臨時(shí)數(shù)組大,接完之后臨時(shí)數(shù)組就變成有序的數(shù)組了,那么再將臨時(shí)數(shù)組的元素復(fù)制到實(shí)際數(shù)組中去,最后釋放臨時(shí)數(shù)組空間,輸出實(shí)際數(shù)組,歸并排序結(jié)束,輸出的元素也是排好序的元素了。
這樣干講一定很抽象
這是b站視頻里的圖,十分生動(dòng)形象了吧。
代碼如下(除了視頻里的注釋?zhuān)€加了點(diǎn)自己的注釋?zhuān)?/p>
#include<bits/stdc++.h> using namespace std; void print_arr(int arr[], int n){ for(int i=0; i<n; i++){ printf("%d ", arr[i]); } printf("\n"); } //合并 void merge(int arr[], int tempArr[], int left, int mid, int right){ //標(biāo)記左半?yún)^(qū)第一個(gè)未排序元素 int l_pos = left; //標(biāo)記右半?yún)^(qū)第一個(gè)未排序元素 int r_pos = mid+1; //合并數(shù)組由左右半?yún)^(qū)構(gòu)成,臨時(shí)數(shù)組的開(kāi)始位置也就是左半?yún)^(qū)的開(kāi)始位置 int pos = left; //合并 //劃分剛結(jié)束后左右半?yún)^(qū)其實(shí)各自只有一個(gè)元素,那么直接比較大小即為兩個(gè)元素的排序。 while(l_pos <= mid && r_pos <= right){//當(dāng)左右半?yún)^(qū)都含有元素時(shí) if(arr[l_pos] < arr[r_pos]) //左半?yún)^(qū)第一個(gè)剩余元素更小 tempArr[pos++] = arr[l_pos++];//賦值后pos+1,l_pos+1為下一次做準(zhǔn)備 else //右半?yún)^(qū)第一個(gè)剩余元素更小 tempArr[pos++] = arr[r_pos++]; } //當(dāng)右半?yún)^(qū)元素合并完后左半?yún)^(qū)還有元素剩余,此時(shí)右半?yún)^(qū)有序且都比左半?yún)^(qū)元素大 //那么直接將剩余的右半?yún)^(qū)元素接上即可 //合并左半?yún)^(qū)剩余的元素 while(l_pos <= mid)tempArr[pos++] = arr[l_pos++]; //同理 //合并右半?yún)^(qū)剩余的元素 while(r_pos <= right)tempArr[pos++] = arr[r_pos++]; //把臨時(shí)數(shù)組中合并后的元素復(fù)制回原來(lái)的數(shù)組 //tempArr此時(shí)已有序,只需利用left,right即排完序后的左右半?yún)^(qū)復(fù)制回arr數(shù)組即可 while(left <= right){ arr[left] = tempArr[left]; left++; } } //歸并排序 void msort(int arr[], int tempArr[], int left, int right){ //如果只有一個(gè)元素,那么就不需要繼續(xù)劃分 //由 mid = (left + right) / 2得,當(dāng)只剩最后一個(gè)數(shù)時(shí) mid會(huì)和left和right相等 //即傳入后的left和right會(huì)相等 if(left < right){ //left和right不相等,不止一個(gè)元素,需要繼續(xù)劃分 //找中間點(diǎn) int mid = (left + right) / 2; //遞歸劃分左半?yún)^(qū) msort(arr, tempArr, left, mid); //遞歸劃分右半?yún)^(qū) msort(arr, tempArr, mid+1, right); //當(dāng)數(shù)組劃分完畢時(shí)開(kāi)始進(jìn)行合并 //合并已經(jīng)排序的部分 //left為左半?yún)^(qū)左邊界 //right為右半?yún)^(qū)右邊界 //mid為劃分左右半?yún)^(qū)的分界(也是左半?yún)^(qū)的右邊界) merge(arr, tempArr, left, mid, right); } } //歸并入口 void merge_sort(int arr[], int n){ //分配一個(gè)輔助的數(shù)組,內(nèi)存大小為 數(shù)組數(shù)*數(shù)據(jù)類(lèi)型占位 int* tempArr = (int*)malloc(n * sizeof(int)); if(tempArr){ //tempArr為臨時(shí)數(shù)組, arr為需要排序的數(shù)組 //排序下標(biāo)為0至n-1,n為數(shù)組大小 msort(arr, tempArr, 0, n-1); free(tempArr);//釋放內(nèi)存空間 } else{ printf("meet error"); } } int main(){ int arr[] = {9, 5, 2, 7, 12, 4, 3, 1, 11}; int n = 9; //打印原來(lái)的數(shù)組 print_arr(arr, n); //歸并排序 merge_sort(arr, n); //打印排完序的數(shù)組 print_arr(arr, n); return 0; }
總結(jié)
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
- C語(yǔ)言非遞歸算法解決快速排序與歸并排序產(chǎn)生的棧溢出
- C語(yǔ)言實(shí)現(xiàn)各種排序算法實(shí)例代碼(選擇,冒泡,插入,歸并,希爾,快排,堆排序,計(jì)數(shù))
- C語(yǔ)言排序方法(冒泡,選擇,插入,歸并,快速)
- C語(yǔ)言分治法實(shí)現(xiàn)歸并排序
- C語(yǔ)言中數(shù)據(jù)結(jié)構(gòu)之鏈表歸并排序?qū)嵗a
- C語(yǔ)言數(shù)據(jù)結(jié)構(gòu) 鏈表與歸并排序?qū)嵗斀?/a>
- C語(yǔ)言實(shí)現(xiàn)排序算法之歸并排序詳解
- c語(yǔ)言排序之歸并排序(遞歸和非遞歸)
相關(guān)文章
C 語(yǔ)言基礎(chǔ)教程(我的C之旅開(kāi)始了)[八]
C 語(yǔ)言基礎(chǔ)教程(我的C之旅開(kāi)始了)[八]...2007-02-02詳解Visual Studio 2019(VS2019) 基本操作
這篇文章主要介紹了詳解Visual Studio 2019(VS2019) 基本操作,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03MoveWindow() SetWindowPos()的區(qū)別于聯(lián)系
這篇文章主要介紹了VC++中MoveWindow() SetWindowPos()的區(qū)別于聯(lián)系,需要的朋友可以參考下2015-01-01詳解C++的反調(diào)試技術(shù)與繞過(guò)手法
反調(diào)試技術(shù),惡意代碼會(huì)用它識(shí)別自身是否被調(diào)試,或者讓調(diào)試器失效,給反病毒工程師們制造麻煩,拉長(zhǎng)提取特征碼的時(shí)間線(xiàn),本章將具體總結(jié)常見(jiàn)的反調(diào)試基礎(chǔ)的實(shí)現(xiàn)原理以及如何過(guò)掉這些反調(diào)試手段,從而讓我們能夠繼續(xù)分析惡意代碼2021-06-06C語(yǔ)言編寫(xiě)實(shí)現(xiàn)學(xué)生管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言編寫(xiě)實(shí)現(xiàn)學(xué)生管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07詳解C++編程中的條件判斷語(yǔ)句if-else與switch的用法
這篇文章主要介紹了C++編程中的條件判斷語(yǔ)句if-else與switch的用法,是C++入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2016-01-01C++實(shí)現(xiàn)LeetCode(134.加油站問(wèn)題)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(134.加油站問(wèn)題),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07基于C++浮點(diǎn)數(shù)(float、double)類(lèi)型數(shù)據(jù)比較與轉(zhuǎn)換的詳解
本篇文章是對(duì)C++中浮點(diǎn)數(shù)(float、double)類(lèi)型數(shù)據(jù)比較與轉(zhuǎn)換進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05