演算法天天見 (二)高階排序

2021-08-29 23:44:05 字數 2964 閱讀 5163

高階排序主要會展示歸併排序演算法和快速排序演算法。歸併排序演算法由於不是原地排序演算法所以它的空間複雜度不是o(1),它的時間複雜度是o(nlogn)。整個演算法如果採用遞迴方式去寫的話是很簡單的,具體可參看**部分。

快速排序的思路和歸併排序是一樣的,就是把陣列分成兩部分分別使其有序最後在組合起來就整體有序了。不同的是快速排序並不是平均拆分陣列,而是選擇乙個中心點,排序時讓中心點左邊的數都比中心點小,中心點右邊數都比中心點大,這個排序演算法的時間複雜度是o(n), 但是由於陣列拆分是基於中心點的,所以它的拆分的時間複雜度和它選擇的這個點有很大關係,具體情況可以看**分析。

/**

** 歸併排序

* 用到的分治的思想

* 假如乙個陣列 前半部分和後半部分都是有序的, 那麼它的排序時間複雜度是o(n)

* 那麼有:

* a(m, n) = a(m, k) + a(k + 1, n)

* 當 m = k 時 說明陣列只有乙個數字那麼它自然有序了

* 同理n = k + 1 也是

* 所以我們只需要把陣列 拆成 長度為乙個 陣列集,排序後再組合起來那麼整個陣列就有序了

* 那麼剩下我們就要看看把陣列 拆成 長度為一的陣列集,需要的時間複雜度是多少

* * 假如陣列長度 為 n, 我們每次 拆一半,最終得到 陣列長度為1

* 數學等式可以寫為:

* n*(1/2)^x = 1 => 2^x = n => x = log(2)n (注意n是log的真數) => o(logn)

* * 所以整個演算法的時間複雜度為: o(nlogn)

* *

* @param s

* */

public

function

mergesort

(s:array)

:void

private

function

merge

(s:array, m:int, n:int)

:array

var k:int = math.

floor

((m + n)/2

);var t1:array =

merge

(s, m, k)

;var t2:array =

merge

(s, k +

1, n)

;//這裡合併成乙個

var q:int =

0, p:int =0;

for(

var i:int =

0; p <= k - m && q <= n - k -

1; i++

)else

}//把剩下的補齊

while

(p <= k-m)

while

(q <= n - k -1)

return temp;

}

/**

*快速排序

* 用到的分治的思想

* 假如乙個陣列 前半部分和後半部分都是有序的, 那麼它的排序時間複雜度是o(n)

* 那麼有:

* a(m, n) = a(m, k) + a(k + 1, n)

* 當 m = k 時 說明陣列只有乙個數字那麼它自然有序了

* 同理n = k + 1 也是

* 所以我們只需要把陣列 拆成 長度為乙個 陣列集,排序後再組合起來那麼整個陣列就有序了

* 那麼剩下我們就要看看把陣列 拆成 長度為一的陣列集,需要的時間複雜度是多少

* * 注意拆分的策略和歸併排序不一樣, 這裡的拆分和選擇的對比點有很大關係

* 我們每次選擇最後乙個點

* 假如選擇點能平分陣列 那麼時間複雜度就和歸併排序一樣 o(logn)

* * 假如陣列是有序的 [1,2,3,4,5,6,7,8],

* 那麼我們拆分的情況就是

* [1,2,3,4,5,6,7,8] => [1,2,3,4,5,6,7] | 8 => [1,2,3,4,5,6] | 7,8 => ... => | 1,2,3,4,5,6,7,8

* 可以看出總共要進行n次拆分 所以時間複雜度是o(n)

* * 而如果輸入是完全無序的[8,7,6,5,4,3,2,1]

* 那麼我們的拆分情況是

* [1,2,3,4,5,6,7,8] => 1 | [2,3,4,5,6,7,8] => 1,2 | [3,4,5,6,7,8] => ... => 1,2,3,4,5,6,7,8 |

* 也是o(n)

* * 所以可以看出,中心點的選擇是很重要的,我們需要盡量選擇可以平分陣列的點

* 它最好的情況是 o(nlogn), 最差的情況是 o(n²)

* * @param s

* */

public

function

quicksort

(s:array)

:void

private

function

quick

(s:array, m:int, n:int)

:void

//每次都選最後乙個作為中心點

var j:int = m;

//已排序區域起始序號

var value:int;

//排序

for(

var i:int = m; i < n; i++

)else

//否則假如元素比它大,則不做任何交換

}//排序完成之後把最後乙個值,與已排序列表的最後一位交換

value = s[j]

; s[j]

= s[n]

; s[n]

= value;

trace

(s);

quick

(s, m, j -1)

;quick

(s, j +

1, n)

;}

WPF天天見系列

為了能更好的實現產品與vista作業系統的移植 相容 擴充套件等等。最近 或許一直 一段時間開始學習wpf的一些相關知識。根據目前的安排,至少還有1個月的時間。正好,可以每天記錄一些問題或者所學的知識。也希望自己能堅持寫下去。我們都相信時間的力量!大寶能天天見,wpf也可以天天寫!持續更新中.閒話w...

WPF天天見系列

為了能更好的實現產品與vista作業系統的移植 相容 擴充套件等等。最近 或許一直 一段時間開始學習wpf的一些相關知識。根據目前的安排,至少還有1個月的時間。正好,可以每天記錄一些問題或者所學的知識。也希望自己能堅持寫下去。我們都相信時間的力量!大寶能天天見,wpf也可以天天寫!持續更新中.閒話w...

WPF天天見系列 閒話WPF之一(WPF的結構)

wpf可以認為是ms利用原有.net框架的一些特色,加上dirextx的產物。從下圖的wpf元件中,我們可以看出最底層仍然是一些核心api。以下兩張都來自網際網路。其中紅色顯示的元件是wpf的核心。milcore是乙個和directx互動的非託管元件,非託管 能帶給我們更高效的處理,能更好的和dir...