一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java經典排序算法之歸并排序詳解

Java經典排序算法之歸并排序詳解

2020-09-06 15:39歐陽鵬 Java教程

這篇文章主要為大家詳細介紹了Java經典排序算法之歸并排序,具有一定的參考價值,感興趣的小伙伴們可以參考一下

一、歸并排序

歸并排序是建立在歸并操作上的一種有效的排序算法,該算法是采用分治法(divide and conquer)的一個非常典型的應用。將已有序的子序列合并,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。若將兩個有序表合并成一個有序表,稱為二路歸并。

歸并過程為:比較a[i]和a[j]的大小,若a[i]≤a[j],則將第一個有序表中的元素a[i]復制到r[k]中,并令i和k分別加上1;否則將第二個有序表中的元素a[j]復制到r[k]中,并令j和k分別加上1,如此循環下去,直到其中一個有序表取完,然后再將另一個有序表中剩余的元素復制到r中從下標k到下標t的單元。歸并排序的算法我們通常用遞歸實現,先把待排序區間[s,t]以中點二分,接著把左邊子區間排序,再把右邊子區間排序,最后把左區間和右區間用一次歸并操作合并成有序的區間[s,t]。

二、歸并操作

Java經典排序算法之歸并排序詳解

三、兩路歸并算法

1、算法基本思路

     設兩個有序的子文件(相當于輸入堆)放在同一向量中相鄰的位置上:r[low..m],r[m+1..high],先將它們合并到一個局部的暫存向量r1(相當于輸出堆)中,待合并完成后將r1復制回r[low..high]中。

(1)合并過程

     合并過程中,設置i,j和p三個指針,其初值分別指向這三個記錄區的起始位置。合并時依次比較r[i]和r[j]的關鍵字,取關鍵字較小的記錄復制到r1[p]中,然后將被復制記錄的指針i或j加1,以及指向復制位置的指針p加1。
     重復這一過程直至兩個輸入的子文件有一個已全部復制完畢(不妨稱其為空),此時將另一非空的子文件中剩余記錄依次復制到r1中即可。

(2)動態申請r1

     實現時,r1是動態申請的,因為申請的空間可能很大,故須加入申請空間是否成功的處理。

2、歸并算法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void merge(seqlist r,int low,int m,int high)
 {//將兩個有序的子文件r[low..m)和r[m+1..high]歸并成一個有序的
 //子文件r[low..high]
 int i=low,j=m+1,p=0//置初始值
 rectype *r1; //r1是局部向量,若p定義為此類型指針速度更快
 r1=(reetype *)malloc((high-low+1)*sizeof(rectype));
 if(! r1) //申請空間失敗
 error("insufficient memory available!");
 while(i<=m&&j<=high) //兩子文件非空時取其小者輸出到r1[p]上
 r1[p++]=(r[i].key<=r[j].key)?r[i++]:r[j++];
 while(i<=m) //若第1個子文件非空,則復制剩余記錄到r1中
 r1[p++]=r[i++];
 while(j<=high) //若第2個子文件非空,則復制剩余記錄到r1中
 r1[p++]=r[j++];
 for(p=0,i=low;i<=high;p++,i++)
 r[i]=r1[p];//歸并完成后將結果復制回r[low..high]
 } //merge

四、歸并排序

歸并排序有兩種實現方法:自底向上和自頂向下。下面說說自頂向下的方法    

(1)分治法的三個步驟

設歸并排序的當前區間是r[low..high],分治法的三個步驟是:
①分解:將當前區間一分為二,即求分裂點        
②求解:遞歸地對兩個子區間r[low..mid]和r[mid+1..high]進行歸并排序;
③組合:將已排序的兩個子區間r[low..mid]和r[mid+1..high]歸并為一個有序的區間r[low..high]。
遞歸的終結條件:子區間長度為1(一個記錄自然有序)。

(2)具體算法

?
1
2
3
4
5
6
7
8
9
10
void mergesortdc(seqlist r,int low,int high)
 {//用分治法對r[low..high]進行二路歸并排序
 int mid;
 if(low<high){//區間長度大于1
  mid=(low+high)/2//分解
  mergesortdc(r,low,mid); //遞歸地對r[low..mid]排序
  mergesortdc(r,mid+1,high); //遞歸地對r[mid+1..high]排序
  merge(r,low,mid,high); //組合,將兩個有序區歸并為一個有序區
 }
 }//mergesortdc

(3)算法mergesortdc的執行過程

算法mergesortdc的執行過程如下圖所示的遞歸樹。

Java經典排序算法之歸并排序詳解

五、算法分析

1、穩定性

歸并排序是一種穩定的排序。

2、存儲結構要求

可用順序存儲結構。也易于在鏈表上實現。

3、時間復雜度

對長度為n的文件,需進行 趟二路歸并,每趟歸并的時間為o(n),故其時間復雜度無論是在最好情況下還是在最壞情況下均是o(nlgn)。

4、空間復雜度

需要一個輔助向量來暫存兩有序子文件歸并的結果,故其輔助空間復雜度為o(n),顯然它不是就地排序。

注意:

若用單鏈表做存儲結構,很容易給出就地的歸并排序。

5、比較操作的次數介于(nlogn) / 2和nlogn - n + 1。

6、賦值操作的次數是(2nlogn)。歸并算法的空間復雜度為:0 (n)

7、歸并排序比較占用內存,但卻是一種效率高且穩定的算法。

六、代碼實現

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
public class mergesorttest {
 
 public static void main(string[] args) {
 int[] data = new int[] { 2, 4, 7, 5, 8, 1, 3, 6 };
 system.out.print("初始化:\t");
 print(data);
 system.out.println("");
 
 mergesort(data, 0, data.length - 1);
  
 system.out.print("\n排序后: \t");
 print(data);
 }
 
 public static void mergesort(int[] data, int left, int right) {
 if (left >= right)
  return;
 //兩路歸并
 // 找出中間索引
 int center = (left + right) / 2;
 // 對左邊數組進行遞歸
 mergesort(data, left, center);
 // 對右邊數組進行遞歸
 mergesort(data, center + 1, right);
 // 合并
 merge(data, left, center, center + 1, right);
 system.out.print("排序中:\t");
 print(data);
 }
 
 /**
 * 將兩個數組進行歸并,歸并前面2個數組已有序,歸并后依然有序
 *
 * @param data
 *  數組對象
 * @param leftstart
 *  左數組的第一個元素的索引
 * @param leftend
 *  左數組的最后一個元素的索引
 * @param rightstart
 *  右數組第一個元素的索引
 * @param rightend
 *  右數組最后一個元素的索引
 */
 public static void merge(int[] data, int leftstart, int leftend,
  int rightstart, int rightend) {
 int i = leftstart;
 int j = rightstart;
 int k = 0;
 // 臨時數組
 int[] temp = new int[rightend - leftstart + 1]; //創建一個臨時的數組來存放臨時排序的數組
 // 確認分割后的兩段數組是否都取到了最后一個元素
 while (i <= leftend && j <= rightend) {
  // 從兩個數組中取出最小的放入臨時數組
  if (data[i] > data[j]) {
  temp[k++] = data[j++];
  } else {
  temp[k++] = data[i++];
  }
 }
 // 剩余部分依次放入臨時數組(實際上兩個while只會執行其中一個)
 while (i <= leftend) {
  temp[k++] = data[i++];
 }
 while (j <= rightend) {
  temp[k++] = data[j++];
 }
 k = leftstart;
 // 將臨時數組中的內容拷貝回原數組中 // (原left-right范圍的內容被復制回原數組)
 for (int element : temp) {
  data[k++] = element;
 }
 }
 
 public static void print(int[] data) {
 for (int i = 0; i < data.length; i++) {
  system.out.print(data[i] + "\t");
 }
 system.out.println();
 }
}

七、運行結果

?
1
2
3
4
5
6
7
8
9
10
11
初始化: 2 4 7 5 8 1 3 6
 
排序中: 2 4 7 5 8 1 3 6
排序中: 2 4 5 7 8 1 3 6
排序中: 2 4 5 7 8 1 3 6
排序中: 2 4 5 7 1 8 3 6
排序中: 2 4 5 7 1 8 3 6
排序中: 2 4 5 7 1 3 6 8
排序中: 1 2 3 4 5 6 7 8
 
排序后: 1 2 3 4 5 6 7 8

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:http://blog.csdn.net/ouyang_peng/article/details/46625155

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 欧美日韩中文字幕一区二区高清 | 撕开老师的丝袜白丝扒开粉嫩的小 | 日韩精品免费一区二区三区 | 五月色婷婷久久综合 | 欧美视频在线播放观看免费福利资源 | 亚洲欧美一区二区久久 | 国产va欧美va在线观看 | 国产一区精品视频 | 99久久精品免费看国产一区 | 亚洲精品视频久久 | 久久足恋网 | 欧美草逼网站 | 午夜爽喷水无码成人18禁三级 | 性bbwbbwbbwbbw撒尿 | 国内自拍网红在综合图区 | 成人网免费视频 | 日本无卡码一区二区三区 | 国产成+人+亚洲+欧美综合 | 国产免费一区二区三区 | 亚洲人成网站在线观看90影院 | 日本一在线中文字幕天堂 | 色菇凉天天综合网 | 欧美亚洲桃花综合 | 14一18cad中国大学生 | 好大好爽好涨太深了小喜 | 国产自拍视频网站 | 久久久亚洲国产精品主播 | java hd国产高清 | 99re5在线精品视频热线 | 鬼吹灯之天星术免费观看 | 放荡警察巨r麻麻出轨小说 范冰冰特黄xx大片 饭冈加奈子在线播放观看 法国老妇性xx在线播放 | 轻轻色在线视频中文字幕 | 男女车车好快的车车免费网站 | 草莓绿巨人香蕉茄子芭乐 | 四虎影视在线看免费 720p | 欧美国产精品久久 | 国产亚洲精品一区二区在线观看 | 女bbbbxxx孕妇| 欧美最猛性xxxxx69交 | 精品午夜久久网成年网 | 国产精品自在线拍 |