归并排序(代码注释超详细)
生活随笔
收集整理的這篇文章主要介紹了
归并排序(代码注释超详细)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
歸并排序:
? ? ? ? ? ? ? (復制粘貼百度百科沒什么意思),簡單來說,就是對數組進行分組,然后分組進行排序,排序完最后再整合起來排序!
我看了很多博客,都是寫的8個數據呀什么的(2^4,分組方便),我就想著,要是10個數據呢,他們那種就沒怎么講清楚,下面我來講一下我所理解的歸并排序!
思路整理如下所示:
?下面用代碼來實現(代碼注釋超詳細):
用來判斷整合幾次的最外層循環!
void MergeSort(int *arr, int len) //這塊用了函數調用 當然你給上面那玩意寫到這個里面完全可以
{for(int i=1; i<len; i*=2)//首先來看假如數組有八位滿足不滿足條件 (2^3)<8不成立 也就是四四合并之后 就完成了合并 查看上面圖 滿足條件//再來看假如有10個值 (2^4)<10不成立 也就是八八合并之后 需要四次合并 查看上圖 滿足條件{Merge(arr, len, i); //調用函數主體 直接寫到這個循環中也完全ok}
}
函數主體:
//8 6 3 2 7 1 9 5 4 0
//如上所示 單個數的時候 L1 = H1就是這個數字本身
//68 23 17 59 04
//這塊拿前兩個分好的數組為例 arr[L1] = 6 arr[H1] = 8 arr[L2] = 2 arr[H2] = 3
//2368 1579 04
//拿這組舉例的話 arr[L1] = 2 arr[H1] = 8 arr[L2] = 1 arr[H2] = 9
//12356789 04
//arr[L1] = 1 arr[H1] = 9 arr[L2] = 0 arr[H2] = 4
void Merge(int* arr, int len, int gap)
{//數組本身空間不夠,這塊早堆區申請一個和數組等長的動態內存int* brr = (int*)malloc(sizeof(int) * len);assert(brr != NULL);//int L1 = 0; //這塊就到歸并排序的精髓了 假設第一步,gap的值是1 一一合并L1 = 0 H1 = 0int H1 = L1 + gap - 1; //接上行 合并之后L1 = 0,H1 = 1int L2 = H1 + 1; //到這兒之后 按照上圖來說68 23 arr[L1] = 6 arr[H1] = 8;int H2 = L2 + gap - 1 < len ? L2 + gap - 1 : len - 1;//那么arr[L2] = 2 arr[H2] = 3 ; L2 = H1 + 1 = 2 ; //H2 = L2 + gap - 1 < len ? L2 + gap - 1 : len - 1 = 3;這里寫個三目運算符主要是用來判斷L2+gap如果越界len的話,那么H2的下標值為len-1int i = 0;// 堆區申請來的空間brr存放數據的下標while (L2 < len) //這塊為什么要L2 < len 呢 先想一下 如果用L1 H1的話 跑到后期 L2早就越界了導致左邊的白跑{ //然后使用L2的時候可以保證右邊的數組最少取到一個值 使用H2的話會導致提前越界 導致有些數據不能成功排序while (L1 < H1 && L2 < H2){if (arr[L1] <= arr[L2]){brr[i++] = arr[L1++]; //這塊后置++的原因是先用再加 難以理解的話可以寫成下面這種/*brr[i] = arr[L1];i++, L1++;*/}else{brr[i++] = arr[L2++];}}while (L1 <= H1)//因為上面的內層while中是 "&&" 可能其中一項滿足 但是另外一項不滿足 因此退出了while循環 因此寫這么一句 { //如果左邊還有數據 挪下來brr[i++] = arr[L1++];}while (L2 <= H2)//如果右邊組還有數據,挪下來{brr[i++] = arr[L2++];}L1 = H2 + 1; //因為數據得遍歷完分組排序 這是在新的分好的數組中的左值與右值 與上面一毛一樣H1 = L1 + gap - 1;L2 = H1 + 1;H2 = L2 + gap - 1 < len ? L2 + gap - 1 : len - 1;}//這塊退出while就是右邊的arr中數組L2越界了(while(L2<len)) 此時右邊肯定沒有數據了//至于arr中左邊的數組還有沒有值 不確定再來個判斷while (L1 < len){brr[i++] = arr[L1++];}//然后再將brr中數組導入到arr中即可 for (int i = 0; i < len; i++){arr[i] = brr[i];}free(brr); //堆區空間的釋放
}
將代碼寫一塊就是:
//8 6 3 2 7 1 9 5 4 0
//如上所示 單個數的時候 L1 = H1就是這個數字本身
//68 23 17 59 04
//這塊拿前兩個分好的數組為例 arr[L1] = 6 arr[H1] = 8 arr[L2] = 2 arr[H2] = 3
//2368 1579 04
//拿這組舉例的話 arr[L1] = 2 arr[H1] = 8 arr[L2] = 1 arr[H2] = 9
//12356789 04
//arr[L1] = 1 arr[H1] = 9 arr[L2] = 0 arr[H2] = 4
void Merge(int* arr, int len, int gap)
{//數組本身空間不夠,這塊早堆區申請一個和數組等長的動態內存int* brr = (int*)malloc(sizeof(int) * len);assert(brr != NULL);//int L1 = 0; //這塊就到歸并排序的精髓了 假設第一步,gap的值是1 一一合并L1 = 0 H1 = 0int H1 = L1 + gap - 1; //接上行 合并之后L1 = 0,H1 = 1int L2 = H1 + 1; //到這兒之后 按照上圖來說68 23 arr[L1] = 6 arr[H1] = 8;int H2 = L2 + gap - 1 < len ? L2 + gap - 1 : len - 1;//那么arr[L2] = 2 arr[H2] = 3 ; L2 = H1 + 1 = 2 ; //H2 = L2 + gap - 1 < len ? L2 + gap - 1 : len - 1 = 3;這里寫個三目運算符主要是用來判斷L2+gap如果越界len的話,那么H2的下標值為len-1int i = 0;// 堆區申請來的空間brr存放數據的下標while (L2 < len) //這塊為什么要L2 < len 呢 先想一下 如果用L1 H1的話 跑到后期 L2早就越界了導致左邊的白跑{ //然后使用L2的時候可以保證右邊的數組最少取到一個值 使用H2的話會導致提前越界 導致有些數據不能成功排序while (L1 < H1 && L2 < H2){if (arr[L1] <= arr[L2]){brr[i++] = arr[L1++]; //這塊后置++的原因是先用再加 難以理解的話可以寫成下面這種/*brr[i] = arr[L1];i++, L1++;*/}else{brr[i++] = arr[L2++];}}while (L1 <= H1)//因為上面的內層while中是 "&&" 可能其中一項滿足 但是另外一項不滿足 因此退出了while循環 因此寫這么一句 { //如果左邊還有數據 挪下來brr[i++] = arr[L1++];}while (L2 <= H2)//如果右邊組還有數據,挪下來{brr[i++] = arr[L2++];}L1 = H2 + 1; //因為數據得遍歷完分組排序 這是在新的分好的數組中的左值與右值 與上面一毛一樣H1 = L1 + gap - 1;L2 = H1 + 1;H2 = L2 + gap - 1 < len ? L2 + gap - 1 : len - 1;}//這塊退出while就是右邊的arr中數組L2越界了(while(L2<len)) 此時右邊肯定沒有數據了//至于arr中左邊的數組還有沒有值 不確定再來個判斷while (L1 < len){brr[i++] = arr[L1++];}//然后再將brr中數組導入到arr中即可 for (int i = 0; i < len; i++){arr[i] = brr[i];}free(brr); //堆區空間的釋放
}void MergeSort(int *arr, int len) //這塊用了函數調用 當然你給上面那玩意寫到這個里面完全可以
{for(int i=1; i<len; i*=2)//首先來看假如數組有八位滿足不滿足條件 (2^3)<8不成立 也就是四四合并之后 就完成了合并 查看上面圖 滿足條件//再來看假如有10個值 (2^4)<10不成立 也就是八八合并之后 需要四次合并 查看上圖 滿足條件{Merge(arr, len, i); //調用函數主體 直接寫到這個循環中也完全ok}
}
主要就是H2的取值怎么取值和思路是重點那塊是重點!
“但凡辛苦,皆是禮物”
總結
以上是生活随笔為你收集整理的归并排序(代码注释超详细)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 开国大典画是谁画的啊?
- 下一篇: 男方不育做试管婴儿吗