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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

归并排序 java_马士兵说之归并排序

發布時間:2024/7/23 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 归并排序 java_马士兵说之归并排序 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

大家對于排序應該是挺熟悉的吧,馬士兵老師特意為排序出了一波視頻,當然文章是轉自博客園的,馬士兵老師的視頻觀看請點擊下方的了解更多

概要

本章介紹排序算法中的歸并排序。內容包括:

1. 歸并排序介紹

2. 歸并排序圖文說明

3. 歸并排序的時間復雜度和穩定性

4. 歸并排序實現

4.1 歸并排序C實現

4.2 歸并排序C++實現

4.3 歸并排序Java實現


更多排序和算法請參考:數據結構與算法系列 目錄

歸并排序介紹

將兩個的有序數列合并成一個有序數列,我們稱之為"歸并"。

歸并排序(Merge Sort)就是利用歸并思想對數列進行排序。根據具體的實現,歸并排序包括"從上往下"和"從下往上"2種方式。

1. 從下往上的歸并排序:將待排序的數列分成若干個長度為1的子數列,然后將這些數列兩兩合并;得到若干個長度為2的有序數列,再將這些數列兩兩合并;得到若干個長度為4的有序數列,再將它們兩兩合并;直接合并成一個數列為止。這樣就得到了我們想要的排序結果。(參考下面的圖片)

2. 從上往下的歸并排序:它與"從下往上"在排序上是反方向的。它基本包括3步:

① 分解 -- 將當前區間一分為二,即求分裂點 mid = (low + high)/2;

② 求解 -- 遞歸地對兩個子區間a[low...mid] 和 a[mid+1...high]進行歸并排序。遞歸的終結條件是子區間長度為1。

③ 合并 -- 將已排序的兩個子區間a[low...mid]和 a[mid+1...high]歸并為一個有序的區間a[low...high]。

下面的圖片很清晰的反映了"從下往上"和"從上往下"的歸并排序的區別。

歸并排序圖文說明

歸并排序(從上往下)代碼

/* * 將一個數組中的兩個相鄰有序區間合并成一個 * * 參數說明: * a -- 包含兩個有序區間的數組 * start -- 第1個有序區間的起始地址。 * mid -- 第1個有序區間的結束地址。也是第2個有序區間的起始地址。 * end -- 第2個有序區間的結束地址。 */void merge(int a[], int start, int mid, int end){ int *tmp = (int *)malloc((end-start+1)*sizeof(int)); // tmp是匯總2個有序區的臨時區域 int i = start; // 第1個有序區的索引 int j = mid + 1; // 第2個有序區的索引 int k = 0; // 臨時區域的索引 while(i <= mid && j <= end) { if (a[i] <= a[j]) tmp[k++] = a[i++]; else tmp[k++] = a[j++]; } while(i <= mid) tmp[k++] = a[i++]; while(j <= end) tmp[k++] = a[j++]; // 將排序后的元素,全部都整合到數組a中。 for (i = 0; i < k; i++) a[start + i] = tmp[i]; free(tmp);}/* * 歸并排序(從上往下) * * 參數說明: * a -- 待排序的數組 * start -- 數組的起始地址 * endi -- 數組的結束地址 */void merge_sort_up2down(int a[], int start, int end){ if(a==NULL || start >= end) return ; int mid = (end + start)/2; merge_sort_up2down(a, start, mid); // 遞歸排序a[start...mid] merge_sort_up2down(a, mid+1, end); // 遞歸排序a[mid+1...end] // a[start...mid] 和 a[mid...end]是兩個有序空間, // 將它們排序成一個有序空間a[start...end] merge(a, start, mid, end);}

從上往下的歸并排序采用了遞歸的方式實現。它的原理非常簡單,如下圖:

通過"從上往下的歸并排序"來對數組{80,30,60,40,20,10,50,70}進行排序時:

1. 將數組{80,30,60,40,20,10,50,70}看作由兩個有序的子數組{80,30,60,40}和{20,10,50,70}組成。對兩個有序子樹組進行排序即可。

2. 將子數組{80,30,60,40}看作由兩個有序的子數組{80,30}和{60,40}組成。

將子數組{20,10,50,70}看作由兩個有序的子數組{20,10}和{50,70}組成。

3. 將子數組{80,30}看作由兩個有序的子數組{80}和{30}組成。

將子數組{60,40}看作由兩個有序的子數組{60}和{40}組成。

將子數組{20,10}看作由兩個有序的子數組{20}和{10}組成。

將子數組{50,70}看作由兩個有序的子數組{50}和{70}組成。

歸并排序(從下往上)代碼

/* * 對數組a做若干次合并:數組a的總長度為len,將它分為若干個長度為gap的子數組; * 將"每2個相鄰的子數組" 進行合并排序。 * * 參數說明: * a -- 待排序的數組 * len -- 數組的長度 * gap -- 子數組的長度 */void merge_groups(int a[], int len, int gap){ int i; int twolen = 2 * gap; // 兩個相鄰的子數組的長度 // 將"每2個相鄰的子數組" 進行合并排序。 for(i = 0; i+2*gap-1 < len; i+=(2*gap)) { merge(a, i, i+gap-1, i+2*gap-1); } // 若 i+gap-1 < len-1,則剩余一個子數組沒有配對。 // 將該子數組合并到已排序的數組中。 if ( i+gap-1 < len-1) { merge(a, i, i + gap - 1, len - 1); }}/* * 歸并排序(從下往上) * * 參數說明: * a -- 待排序的數組 * len -- 數組的長度 */void merge_sort_down2up(int a[], int len){ int n; if (a==NULL || len<=0) return ; for(n = 1; n < len; n*=2) merge_groups(a, len, n);}

從下往上的歸并排序的思想正好與"從下往上的歸并排序"相反。如下圖:

通過"從下往上的歸并排序"來對數組{80,30,60,40,20,10,50,70}進行排序時:

1. 將數組{80,30,60,40,20,10,50,70}看作由8個有序的子數組{80},{30},{60},{40},{20},{10},{50}和{70}組成。

2. 將這8個有序的子數列兩兩合并。得到4個有序的子樹列{30,80},{40,60},{10,20}和{50,70}。

3. 將這4個有序的子數列兩兩合并。得到2個有序的子樹列{30,40,60,80}和{10,20,50,70}。

4. 將這2個有序的子數列兩兩合并。得到1個有序的子樹列{10,20,30,40,50,60,70,80}。

歸并排序的時間復雜度和穩定性

歸并排序時間復雜度

歸并排序的時間復雜度是O(N*lgN)。

假設被排序的數列中有N個數。遍歷一趟的時間復雜度是O(N),需要遍歷多少次呢?

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

歸并排序穩定性

歸并排序是穩定的算法,它滿足穩定算法的定義。

算法穩定性 -- 假設在數列中存在a[i]=a[j],若在排序之前,a[i]在a[j]前面;并且排序之后,a[i]仍然在a[j]前面。則這個排序算法是穩定的!

歸并排序實現

下面給出歸并排序的三種實現:C、C++和Java。這三種實現的原理和輸出結果都是一樣的,每一種實現中都包括了"從上往下的歸并排序"和"從下往上的歸并排序"這2種形式。

歸并排序C實現

實現代碼(merge_sort.c)

View Code

歸并排序C++實現

實現代碼(MergeSort.cpp)

View Code

歸并排序Java實現

實現代碼(MergeSort.java)

View Code

上面3種實現的原理和輸出結果都是一樣的。下面是它們的輸出結果:

before sort:80 30 60 40 20 10 50 70 after sort:10 20 30 40 50 60 70 80

文章原作者:http://www.cnblogs.com/skywang12345/p/3602369.html

總結

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

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