演算法手記(6)歸併排序

2022-01-20 13:41:20 字數 1864 閱讀 7827

今天我主要學習基於分治思想的歸併排序演算法,這是分治法的典型應用。廢話不多說,下面直切正題。

概述:將兩個有序陣列歸併成乙個更大的有序陣列,我們稱之為歸併,人們根據這一操作發明了一種簡單的遞迴排序演算法:歸併排序。

歸併排序最吸引人的是它能夠保證任意長度為n的陣列排序所需的時間和nlogn成正比;它的主要缺點是需要額外占用的記憶體空間與n成正比。

分析:實現歸併的一種最簡單的方法是將兩個不同的有序陣列歸併到第三個陣列中,實現的方法很簡單,建立乙個適當的陣列然後將兩個陣列中的元素乙個個從小到大放入這個陣列。但這樣帶來的問題是排序大陣列時,需要多次歸併,每次歸併都建立新的陣列,這無疑會帶來很大的問題。因此,我們需要一種能夠實現原地歸併的方法,這樣就可以先將左邊排序,再將右邊排序,然後在陣列中移動元素而不需要額外的記憶體空間,我們將在實現部分描述這種方法。

實現:原地歸併方法:

private

static

void merge(icomparable a, int lo, int mid, int

hi)

}

下面分別是兩種不同的最終實現演算法,它們都是應用高效演算法設計中分治思想的典型例子。

自頂向下的歸併實現:

public

class

merge

private

static

void sort(icomparable a,int lo,int

hi)

public

static

bool

less(icomparable v, icomparable w)

public

static

void exch(icomparable a, int i, int

j)

public

static

void

show(icomparable a)

private

static

void merge(icomparable a, int lo, int mid, int

hi)

}public

static

void test(int

size);}

console.writeline(

"after sort:");

merge.sort(data);

datetime enddate =datetime.now;

double time = (enddate.hour - startdate.hour) * 3600 * 1000 + (enddate.minute - startdate.minute) * 60 * 1000 + (enddate.second - startdate.second) * 1000 + (enddate.millisecond -startdate.millisecond);

if (time > 1000) time /= 1000

; console.writeline(

"time:

" +time);

}public

static

void main(string

args)

}

自底向上的歸併排序:

public

static

void

sort(icomparable a)

用自頂向下或者自底向上實現分治類演算法都很自然。歸併排序演算法的實現說明,當能夠用一種方式解決乙個問題時,也應該試試另一種方法。其中自底向上的方式適合於組織鍊錶結構,能夠將鍊錶原地排序。

排序演算法6 歸併排序

1.什麼是歸併排序 歸併排序是建立在歸併操作上的一種有效的排序演算法。該演算法是採用分治法 divide and conquer 的乙個非常典型的應用。將已有序的子 序列合併,得到完全有序的序列 即先使每個子串行有序,再使子串行段間有序。若將兩個有序表合併成乙個有序表,稱為2 路歸併。2.演算法步驟...

6 歸併排序

歸併排序是歸併兩個有序的序列,這兩個有序序列需要頭尾兩個指標,遍歷這兩個序列,按照排序規則儲存在乙個可以容納這兩個序列的序列中,當遍歷結束,則新的序列為有序序列。當我們需要對某一串行排序時,可以把該序列分成兩半,分別對這兩半進行排序,然後歸併這兩個有序序列。而這兩半又可以遞迴地分半,類似二分法。in...

6 歸併排序

歸併排序是建立在歸併操作上的一種有效的排序演算法。該演算法是採用分治法 divide and conquer 的乙個非常典型的應用。nlogn 由於需要兩兩比較 因此也是穩定的!首先考慮下如何將將二個有序數列合併。這個非常簡單,只要從比較二個數列的第乙個數,誰小就先取誰,取了後就在對應數列中刪除這個...