兩個有序序列的合併演算法

2021-07-02 04:27:29 字數 2873 閱讀 5268

將兩個有序序列合併(merge)為乙個有序序列問題的形式化表示為:

輸入:序列a[p...r]。其中,子串行a[p...q]和a[q+1...r]是有序的。

輸出:a[p...r]所有元素的重排,使之有序。

用乙個漸增型演算法解決此問題。首先,把a[p...q]和a[q+1...r]分別複製到序列l[1...n1]和r[1...n2]中,其中n1=q-p+1,n2=r-q。然後,維護3個變數i、j和k,i、j初始化為1,k初始化為p。比較l[i]和r[j],將較小者複製到a[k],調整i、j和k使得它們各自指向l、r和a的合適的位置:若l[i]≤r[j],則i增加1,否則j增加1。無論如何k都要增加1,迴圈往復,直至l和r之一被掃瞄完。然後,將另乙個序列中尚存的元素複製到a[k...r]。在此過程中,a[p...k-1]中的元素是a[p...r]中最小的k-p個元素,並且已排好序。隨著k的增長,a[p...k]漸增為乙個有序序列。

merge(a, p, q, r)

1 n1 <-- q - p -1

2 n2 <-- r - q

3 建立陣列l[1...n1]和r[1...n2]

4 for i <-- 1 to n1

5 do l[i] <-- a[p+i-1]

6 for j <-- 1 to n2

7 do r[j] <-- a[q+j]

8 i <-- 1

9 j <-- 1

10 k <-- p

11 while i ≤n1 and j≤n2

12 do if l[i]≤r[j]

13 then a[k] <-- l[i]

14 i <-- i + 1

15 else a[k] <-- r[i]

16 j <-- j +1

17 k <-- k + 1

18 if i < n1

19 then 將l[i...n1]複製到a[k...r]

20 if j < n2

21 then 將r[j...n2]複製到a[k...r]

演算法:解決有序子串行合併問題的merge演算法(徐子珊)

merge(a, b, p, q, r)

1 i <-- p

2 j <-- q + 1

3 k <-- p

11 while i≤q and j≤r

12 do if a[i]≤a[j]

13 then b[k] <-- a[i]

14 i <-- i + 1

15 else b[k] <-- a[j]

16 j <-- j +1

17 k <-- k + 1

18 if i < q

19 then 將a[i...q]複製到b[k...r]

20 if j < r

21 then 將a[j...r]複製到b[k...r]

演算法:解決有序子串行合併問題的merge演算法(王曉東)

假定a[p...r]含有n(=r-p+1)個元素。第4~5行及第6~7行的for迴圈均重複n次,此外第12~17行的while迴圈重複k-p次,第18~21行中的for迴圈將重複r-k+1次,兩者一共耗時o(n)。所以演算法的最壞情形時間為o(n)。

這個過程是乙個更有效的排序演算法----合併排序(歸併排序)中的關鍵步驟。

演算法:解決有序子串行合併問題的merge演算法(徐子珊)

/**

* @methodname:merge2

* @description: 兩個有序子串行的合併(徐子珊)

* @param a 儲存兩個有序子串行

* @param p 前乙個序列的開始位置

* @param q 前乙個序列的結束位置(後乙個序列的開始位置q+1)

* @param r 後乙個序列的結束位置

*/ public static void merge2(int a, int p, int q, int r)

// 把後一串行元素拷貝到輔助陣列b中

for (j = 0; j < n2; j++)

i=j=0;

k=p;

//從i開始遍歷前乙個序列,從j開始遍歷後乙個序列,

//將其中元素較小者存入陣列b中,並更改相應索引位置

while(i < n1 && j < n2)else

} if(i < n1)

} if(j < n2)

} }

演算法:解決有序子串行合併問題的merge演算法(王曉東)

/**

* @methodname:merge

* @description: 兩個有序子串行的合併

* @param a 儲存兩個有序子串行

* @param b 儲存排好序後的序列

* @param left 前乙個序列的開始位置

* @param middle 前乙個序列的結束位置(後乙個序列的開始位置middle+1)

* @param right 後乙個序列的結束位置

*/ public static void merge(int a, int b, int left, int middle, int right)

else

} if(i > middle)

}else

} }

合併兩個有序序列

將兩個有序的數列,合併成乙個有序的序列 package toyprogram this class is used for author dlf 460795365 qq.com version 1.0,2016年9月13日 下午3 39 42 public class aboutarrayl in...

合併兩個有序鍊錶序列

本題要求實現乙個函式,將兩個鍊錶表示的遞增整數序列合併為乙個非遞減的整數序列。list merge list l1,list l2 其中list結構定義如下 typedef struct node ptrtonode struct node typedef ptrtonode list 定義單鏈表型...

兩個有序鍊錶序列的合併

習題2.5 兩個有序鍊錶序列的合併 15分 本題要求實現乙個函式,將兩個鍊錶表示的遞增整數序列合併為乙個非遞減的整數序列。list merge list l1,list l2 其中list結構定義如下 typedef struct node ptrtonode struct node typedef...