排序 歸併與快速排序

2021-08-27 11:23:01 字數 4313 閱讀 4861

歸併排序思想

將陣列一分為二(折半);

分別將兩部分陣列進行排序;

將排序好的兩部分陣列進行合併成新的有序陣列。

動態圖演示

演算法實現

利用分治演算法,自頂向下的進行遞迴排序。動態圖演示則為自下往上的排序演示。

public

static

void

main(string args) ;

sort(array, 0, array.length - 1);

arrayutils.printarray(array);

}private

static

void

sort(int array, int start, int end)

int mid = (end + start) / 2;

sort(array, start, mid); // 左半排序

sort(array, mid + 1, end); // 右半排序

merge(array, start, mid + 1, end); // 歸併

}/**

* 兩個有序的陣列(start->mid - 1, mid->end)原地歸併

*@param array 陣列

*@param start 開始

*@param mid 中間

*@param end 結束

*/public

static

void

merge(int array, int start, int mid, int end)

// 定義兩個陣列的指標,向後遍歷比較

int leftindex = start, rightindex = mid;

for (int i = start; i <= end; i++) else

if (rightindex > end) else

if (copyarray[leftindex - start] <= copyarray[rightindex - start]) else

if (copyarray[leftindex - start] > copyarray[rightindex - start]) }}

演算法評價

排序方法

平均時間複雜度

最壞時間複雜度

最好時間複雜度

空間複雜度

穩定性歸併排序o(

nlog

2n) o(n

log2

n)o(nlog

2n) o(n

log2

n)o(nlog

2n) o(n

log2

n)o(n)o(

n)穩定 - 歸併排序的時間複雜度都是 o(

nlog

2n) o(n

log2

n),但其需要額外的空間開銷;

- 和選擇排序一樣,歸併排序不受輸入序列的影響,但表現比選擇排序好的多;

- 歸併排序並不會影響相同大小資料之間的順序,所以穩定。

快速排序思想

將陣列分為兩部分,使得前一部分的最大值不大於後一部分的最小值(切分處的元素已經排定);

將兩部分陣列進行分別排序;

前一部分、切分元素與後一部分合併成有序陣列。

選定切分位置:

隨意的選取左邊陣列的第乙個元素作為切分元素;

定義首尾指標,頭指標從左向右遍歷,尋找比切分元素大的元素,尾指標從右向左遍歷,尋找比切分元素小的元素,將兩個元素進行交換,使得大的在後,小的在前;

不斷的進行首尾指標移動,直到首尾相遇,這樣就能保證小的元素在頭指標左側,大的元素在尾指標右側;

將首位的切分元素與頭指標指向的元素位置進行交換,這樣快速排序的第一步便完成。

動態圖演示

演算法實現

public

static

void

main(string args) ;

sort(array, 0, array.length - 1);

arrayutils.printarray(array);

}public

static

void

sort(int array, int start, int end)

int mid = partition(array, start, end);

sort(array, start, mid - 1);

sort(array, mid + 1, end);

}/**

* 尋找切分元素,將陣列分成左右兩部分

*@param array 陣列

*@param start 開始

*@param end 結束

*@return 切分元素索引

*/private

static

intpartition(int array, int start, int end)

}// 尋找右邊小於切分元素

while (array[--rightindex] >= array[start])

}// 尋找到的進行替換

if (leftindex >= rightindex)

int temp = array[leftindex];

array[leftindex] = array[rightindex];

array[rightindex] = temp;

}// 最終交換切分位置

int temp = array[start];

array[start] = array[rightindex];

array[rightindex] = temp;

return rightindex;

}

演算法分析

排序方法

平均時間複雜度

最壞時間複雜度

最好時間複雜度

空間複雜度

穩定性快速排序o(

nlog

2n) o(n

log2

n)o(n2

) o(n

2)o(nlog

2n) o(n

log2

n)o(nlog

2n) o(n

log2

n)不穩定

- 快速排序的時間複雜度與歸併排序相當,但是最壞時間複雜度仍然是 o(

n2) o(n

2); - 空間複雜度由於需要交換位置,需要額外開闢空間;

- 快速排序由於尋找切分元素會進行交換位置,切分元素最後也會交換位置,破壞了穩定性;

- 快速排序的切分需要盡可能的將陣列切成差不多長的兩部分,才能保證快速。否則,每乙隻切乙個元素,導致乙個大陣列需要切很多次。解決該問題,一般排序前將陣列重新混洗,或者尋找切分元素時,隨機確定乙個起始切分元素。

演算法改進

如果陣列中存在大量重複元素,我們可以進行三向切分,每次分為小於切分元素、等於切分元素和大於切分元素三部分。對應的一次排布操作如下:

改進實現

/**

* 三向切分的快速排序

*@param array

*@param start

*@param end

*/public

static

void

sort3way(int array, int start, int end)

// 定義三個指標和切分元素

int lt = start, i = start + 1, gt = end;

int div = array[start];

while (i <= gt) else

if (array[i] > div) else

}sort(array, start, lt - 1);

sort(array, gt + 1, end);

}

歸併與基數排序

1.輸入10 5個只有一位數字的整數,可以用o n 複雜度將其排序的演算法是 桶排序 2.資料序列只能是下列哪種排序演算法的兩趟排序結果?b a 氣泡排序 b 快速排序 c 插入排序 d 堆排序 解析 如果是氣泡排序,末尾是最大或最小的兩個數 如果是插入排序,最前面應該是最大或最小的兩個數 如果是堆...

歸併,快速排序

歸併排序 實現思想 歸併的含義很明顯就是將兩個或者兩個以上的有序表組合成乙個新的有序表。歸併排序中一般所用到的是2 路歸併排序,即將含有n個元素的序列看成是n個有序的子串行,每個子串行的長度為1,而後兩兩合併,得到n 2個長度為2或1的有序子串行,再進行兩兩合併。直到最後由兩個有序的子串行合併成為乙...

快速排序 歸併排序

感覺好久之前不寫這些基礎的東西忽然覺著,想複習一下,就簡單溫習一下排序的例子 package com.ruishenh.algoritmic public class sort static void printmsg int arrs system.out.println static int g...