歸併排序

 研究過歸併排序和堆排序的時間複雜度的朋友們應該知道它們的時間複雜度都是nlog2n。堆排序是利用了完全二叉樹,做了很多次堆調整才達到了排序的目的。相關堆排序的內容可以看看選擇排序的升級---堆排序,在此不多贅述。
   其實歸併排序也是形似二叉樹。簡單來講就是分而治之的思想。談到 ‘分’很容易想到快速排序,快排也是分。但它是把數列從樞軸點分開。讓點的邊左都小 右邊都大(降序則相反) ,快排分的關鍵點在於樞軸點的篩選。而歸併排序的 ‘分’ 只是歸併的一部分。‘分’是爲了歸併。簡單來說,如果我要讓兩個數列歸併成一個有序數列的前提 是 你給我的兩個數列得本來就是有序的。如何保證給的兩個數列是有序的呢?那就得保證 這兩個數列 分別又是各由兩個有序列歸併來的。
那麼這豈不是無窮無盡了嗎?其實是有盡頭的。那就是如果某個數列長度爲2。那麼它就是由兩個數字歸併來的。這兩個數字分別都是有序的。一個數字就是有序的啊!
所以歸併的前提是一直把數列兩兩劃分。分到不能分的程度的時候我們再使用歸併。

代碼如下:



Merge部分的代碼爲歸併,它讓以s下標爲開頭,e下標爲結尾 中間m下標爲分界點的兩個數組歸併(其實是整個 arr 數組中的一段數組,我們看作是以m劃分的兩段)。歸併算法很簡單。因爲兩個數組分別都有序了,我們只要從任意數組A或B開始,下標爲i和j。讓i下標和j下標對應的值比較,誰小就放在臨時數組tmp中。直到某一個下標到終點了(i的終點爲m,j的終點爲e)。我們不用比較了,然後讓那個沒到終點的下標,到終點,並把值放到tmp裏。最後tmp裏就是個有序數列了,把tmp在全部覆蓋給我要需要排序的arr裏。
示意圖:

MergerSort裏的除過Merge的部分其實就是遞歸劃分。一層層遞歸下去後,當s>=e的時候。即數列的開始下標沒有末尾下標大了。那就是開始下標和末尾下標相等了,代表已經劃分成了一個數字的地步了,就不需要繼續分了。然後遞歸結束一層層收回,收回的時候都會執行Merge(arr,tmp,s,mid,e);語句,就會往回歸併。
 示意圖:  



10萬個隨機數據測試結果:


最後時間複雜度均爲O(nlog2n)    空間複雜度爲O(N)
值得注意的是 穩定性是穩定的。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章