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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

排序七 归并排序

發布時間:2025/3/15 编程问答 14 豆豆
生活随笔 收集整理的這篇文章主要介紹了 排序七 归并排序 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

要點

歸并排序是建立在歸并操作上的一種有效的排序算法,該算法是采用分治法(Divide and Conquer的一個非常典型的應用。

將已有序的子序列合并,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。若將兩個有序表合并成一個有序表,稱為二路歸并

?

歸并排序的基本思想

將待排序序列R[0...n-1]看成是n個長度為1的有序序列,將相鄰的有序表成對歸并,得到n/2個長度為2的有序表;將這些有序序列再次歸并,得到n/4個長度為4的有序序列;如此反復進行下去,最后得到一個長度為n的有序序列。

綜上可知:

歸并排序其實要做兩件事:

1)“分解”——將序列每次折半劃分

2)“合并”——將劃分后的序列段兩兩合并后排序

?

我們先來考慮第二步,如何合并

在每次合并過程中,都是對兩個有序的序列段進行合并,然后排序。

這兩個有序序列段分別為?R[low, mid]??R[mid+1, high]

先將他們合并到一個局部的暫存數組R2中,帶合并完成后再將R2復制回R中。

為了方便描述,我們稱?R[low, mid]?第一段,R[mid+1, high]?為第二段。

每次從兩個段中取出一個記錄進行關鍵字的比較,將較小者放入R2中。最后將各段中余下的部分直接復制到R2中。

經過這樣的過程,R2已經是一個有序的序列,再將其復制回R中,一次合并排序就完成了。

核心代碼

public?void?Merge(int[]?array,?int?low,?int?mid,?int?high)?{
????int?i?=?low;?//?i是第一段序列的下標
????int?j?=?mid?+?1;?//?j是第二段序列的下標
????int?k?=?0;?//?k是臨時存放合并序列的下標
????int[]?array2?=?new?int[high?-?low?+?1];?//?array2是臨時合并序列

????
//?掃描第一段和第二段序列,直到有一個掃描結束
????while?(i?<=?mid?&&?j?<=?high)?{
????????//?判斷第一段和第二段取出的數哪個更小,將其存入合并序列,并繼續向下掃描
????????if?(array[i]?<=?array[j])?{
????????????array2[k]?=?array[i];
????????????i++;
????????????k++;
????????}?else?{
????????????array2[k]?=?array[j];
????????????j++;
????????????k++;
????????}
????}

????//?若第一段序列還沒掃描完,將其全部復制到合并序列
????while?(i?<=?mid)?{
????????array2[k]?=?array[i];
????????i++;
????????k++;
????}

????//?若第二段序列還沒掃描完,將其全部復制到合并序列
????while?(j?<=?high)?{
????????array2[k]?=?array[j];
????????j++;
????????k++;
????}

????//?將合并序列復制到原始序列中
????for?(k?=?0,?i?=?low;?i?<=?high;?i++,?k++)?{
????????array[i]?=?array2[k];
????}
}

掌握了合并的方法,接下來,讓我們來了解??如何分解

在某趟歸并中,設各子表的長度為gap,則歸并前R[0...n-1]中共有n/gap個有序的子表:R[0...gap-1], R[gap...2*gap-1], ... , R[(n/gap)*gap ... n-1]

調用Merge將相鄰的子表歸并時,必須對表的特殊情況進行特殊處理。

若子表個數為奇數,則最后一個子表無須和其他子表歸并(即本趟處理輪空):若子表個數為偶數,則要注意到最后一對子表中后一個子表區間的上限為n-1?

核心代碼

public?void?MergePass(int[]?array,?int?gap,?int?length)?{
????int?i?=?0;

????//?歸并gap長度的兩個相鄰子表
????for?(i?=?0;?i?+?2?*?gap?-?1?<?length;?i?=?i?+?2?*?gap)?{
????????Merge(array,?i,?i?+?gap?-?1,?i?+?2?*?gap?-?1);
????}

????//?余下兩個子表,后者長度小于gap
????if?(i?+?gap?-?1?<?length)?{
????????Merge(array,?i,?i?+?gap?-?1,?length?-?1);
????}
}

public?int[]?sort(int[]?list)?{
????for?(int?gap?=?1;?gap?<?list.length;?gap?=?2?*?gap)?{
????????MergePass(list,?gap,?list.length);
????????System.out.print("gap?=?"?+?gap?+?":\t");
????????this.printAll(list);
????}
????return?list;
}


算法分析

歸并排序算法的性能

排序類別

排序方法

時間復雜度

空間復雜度

穩定性

復雜性

平均情況

最壞情況

最好情況

歸并排序

歸并排序

O(nlog2n)

O(nlog2n)

O(nlog2n)

O(n)

穩定

較復雜

?

時間復雜度

歸并排序的形式就是一棵二叉樹,它需要遍歷的次數就是二叉樹的深度,而根據完全二叉樹的可以得出它的時間復雜度是O(n*log2n)

?

空間復雜度

由前面的算法說明可知,算法處理過程中,需要一個大小為n的臨時存儲空間用以保存合并序列。

?

算法穩定性

在歸并排序中,相等的元素的順序不會改變,所以它是穩定的算法。

?

歸并排序和堆排序、快速排序的比較

若從空間復雜度來考慮:首選堆排序,其次是快速排序,最后是歸并排序。

若從穩定性來考慮,應選取歸并排序,因為堆排序和快速排序都是不穩定的。

若從平均情況下的排序速度考慮,應該選擇快速排序。?


完整參考代碼

Java版本

?View Code


運行結果
?

排序前: ? ? 9???1???5???3???4???2???6???8???7??
gap?=?1:???1???9???3???5???2???4???6???8???7??
gap?=?2:???1???3???5???9???2???4???6???8???7??
gap?=?4:???1???2???3???4???5???6???8???9???7??
gap?=?8:???1???2???3???4???5???6???7???8???9??
排序后: ? ? 1???2???3???4???5???6???7???8???9 ?

本文轉自靜默虛空博客園博客,原文鏈接:http://www.cnblogs.com/jingmoxukong/p/4308823.html,如需轉載請自行聯系原作者

總結

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

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