几分钟学会归并排序和快速排序
文章目錄
- 前言
- 歸并排序
- 快速排序
- 最后
前言
先來看看這兩個排序在常見的排序中的速度比較(50個隨機數(shù)):
再來看看數(shù)據(jù)放大四倍后(200個隨機數(shù))的速度:
可見這兩種排序在大部分的排序算法中脫穎而出,數(shù)據(jù)量較少的時候,快速排序比歸并排序要快,數(shù)據(jù)量變大后,快排略遜一籌。是不是真的呢?讓我們來一起學(xué)習(xí)康康。
(區(qū)別于文章末尾的測試)
(截圖源自手機APP:C語言學(xué)習(xí)寶典)
歸并排序
(截圖源自百度百科)
歸并:顧名思義是把數(shù)據(jù)合并,在這之前需要把他們分開,這是“分”的過程,合并的過程就是“治”的過程。
<畫個草圖>
分:奇數(shù)序列我習(xí)慣給右邊的序列多分一個數(shù)(看網(wǎng)上很多是左邊多分一個數(shù),但我調(diào)試的時候由于邊界問題出bug了就給改了)
治:處理兩個有序列的算法可參考 : 力扣第21題“合并兩個有序鏈表”
用到了類似啞元加迭代的思想,迭代放在兩個有序列起點位置的下標(biāo),每次比較下標(biāo)位置元素大小,按比較條件放入新建立的數(shù)組。
下面是代碼部分:
class myMergesort { public:vector<int> Mergesort(vector<int>& before) {if (before.size() == 1)return before; /*遞歸出口*/vector<int>left, right, ans; /*分*/for (int i = 0; i < before.size() / 2; ++i) /*左切塊*/left.push_back(before[i]);for (int i = before.size() / 2; i < before.size(); ++i)/*右切塊*/right.push_back(before[i]);left=Mergesort(left);/*繼續(xù)切左邊(遞歸)*/right=Mergesort(right);/*繼續(xù)切右邊(遞歸)*//*治*/int i=0, j=0;while(i<left.size()&&j<right.size()) {/*排序插入到ans*/if (left[i] <= right[j])ans.push_back(left[i++]);else ans.push_back(right[j++]);}if (i == left.size()) /*接上right的后續(xù)有序列*/for (int k = j; k < right.size(); ++k)ans.push_back(right[k]);if (j == right.size())/*接上left的后續(xù)有序列*/for (int k = i; k < left.size(); ++k)ans.push_back(left[k]);return ans;} };調(diào)試過程
50個(0~9)隨機數(shù):
20000個(0~9)隨機數(shù):
快速排序
快排:C/C++可直接使用快速排序的庫函數(shù)qsort() / sort()
快排也用到了分治的思想,但它的“分”的過程是依據(jù)基準(zhǔn)數(shù)歸位后所在的位置進行劃分,而基準(zhǔn)數(shù)是什么?怎么“治”?才是快排的關(guān)鍵。
基準(zhǔn)數(shù):通俗講就是每次需要歸位的數(shù),每次歸位后,它的左邊都是比它小的數(shù),它的右邊都是比它大的數(shù)。(一般取最左邊的數(shù)為基準(zhǔn)數(shù))
治:(這里引用到的是《啊哈!算法》中的小插圖)
首先左右哨兵站在序列的左右兩端(下標(biāo)定位,基準(zhǔn)數(shù)為6):
<右邊的哨兵先往左走,找到第一個比6小的數(shù)停下>
<左邊的哨兵再往右走,找到第一個比6大的數(shù)停下>
<然后把他們交換>
哨兵繼續(xù)走,重復(fù)上述過程(交換9和4):
當(dāng)他們相遇,將相遇處的數(shù)字3和基準(zhǔn)數(shù)6交換:
這就完成了一次“治”的過程,然后將此時左邊和右邊的序列進行遞歸,最后返回完成排序。
主代碼部分:
void myQuicksort::_myQuicksort(int left,int right) {if (left >= right)return;int i = left,j=right,base=ans[left],temp;while (i<j) {while (ans[j] >= base && j > i)--j; /*1.右哨兵定位*/while (ans[i] <= base && i < j)++i; /*1.左哨兵定位*/if (i < j) { /*若左右哨兵相遇,取消定位處的交換*//*2.交換左右哨兵定位到的元素*/temp = ans[j];ans[j] = ans[i];ans[i] = temp;}}/*3.交換基準(zhǔn)數(shù)和哨兵相遇處的元素*/ans[left] = ans[i];ans[i] = base;_myQuicksort(left,i-1);/*左邊的無序序列繼續(xù)調(diào)用快排*/_myQuicksort(i+1,right);/*右邊的無序序列繼續(xù)調(diào)用快排*/ }調(diào)試過程:
50個(0~9)隨機數(shù):
20000個(0~9)隨機數(shù):
對比一下,什么?!快排比歸并排序要快!直接打臉了,為什么在app里的結(jié)果不一樣呢…
最后
文章總結(jié)了快排和歸并的原理以及用法,等我以后哪天忘了就來看看。
大家不要復(fù)制粘貼,要認真學(xué)習(xí)總結(jié),不懂的給我留言,哈哈哈還押韻上了,小生不才不當(dāng)?shù)牡胤秸埗喽嘀附獭?/p>
參考:《啊哈!算法》中的排序一章 還有 百度百科。
總結(jié)
以上是生活随笔為你收集整理的几分钟学会归并排序和快速排序的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: wps网盘是什么意思(mac版是什么意思
- 下一篇: idea JDK安装与配置