基於比較的快速排序 時間複雜度為O nlogn

2021-10-05 03:38:44 字數 3639 閱讀 7050

快速排序

快排利用的是分治思想。如果要排序陣列中下標從 p 到 r 之間的一組資料,選擇p 到 r 之間的任意乙個資料作為分割槽點pivot。

遍歷 p 到 r 之間的資料,將小於pivot的放到左邊,將大於pivot的放到右邊,將pivot放到中間。經過這一步驟後陣列 p 到 r 之間的資料就被分為了三個部分。陣列 p 到 r 之間的資料就被分成了三個部分,前面 p

到 q-1 之間都是小於 pivot 的,中間是 pivot,後面的 q+1 到 r 之間是大於 pivot 的。再根據分治、遞迴的處理思想,可以用遞迴排序下標從p 到 q-1之間的資料和下標從q+1到 r 之間的資料,直到區間縮小為 1,就說明所有資料都有序了。

用遞推公式將上面的過程寫出來:

遞推公式:

quicksort

(p…r)

=quicksort

(p…q-1)

+quicksort

(q+1

, r)

終止條件:

p >= r

實現方式

方法1: horea 法:

讓 p 從前往後找,找比基準值大的元素,找到就停止

讓 q 從後往前找,找比基準值小的元素,找到後停止

將 p 和 q 標記的元素進行交換(為了讓前半部分小於後半部分,p 指的是小的)

將基準值和 p 位置的資料進行交換

返回 p

分割的時間複雜度:o(n)

quicksort

(int

arr,

int n)

// 快速排序遞迴函式,p r為下標

quick_sort_c

(int

arr,

int p,

int r)

關於獲取分割槽的方法,關鍵在於資料怎麼劃分,取哪個作為基準值

public

intgetindexofmiddle

(int

arr,

int p,

int q)

else

if(arr[pivot]

> arr[q-1]

)else

}else

else

if(arr[pivot]

< arr[q-1]

)else

}}

找到基準之後分割槽方法的寫法

方法2.挖坑法:

其實基本思路和 hoare 法一致,但是有乙個特點是不再進行數的交換,而是進行賦值 (挖坑+填坑)

p 從前往後找,q 從後往前找,將 q 用key儲存,並認為 q 是坑,只要 q 找到大於 key 的,就把 p 對應得元素覆蓋到 q,此時 p 成為新的坑,然後 q 往前走找比key小的,找到後填 p 這個坑,直到兩個相遇後把key賦給 p 或 q 中任何乙個

分割的時間複雜度:o(n)

分割槽函式的寫法:

private

static

intpartition

(int

array,

int left,

int right)

array[i]

= array[j]

;while

(i < j && array[i]

<= pivot)

array[j]

= array[i];}

array[i]

= pivot;

return i;

}

方法3.前後索引

取基準值,可以取最後的

cur指向當前元素(left)的位置,prev指向cur的前面(prev = cur-1)

// 分割槽函式寫法

private

static

intpartition

(int

array,

int left,

int right)

}swap

(array,d-

1,left)

;return d-1;

}

horea法**實現

public

class

quicksort

// 快速排序遞迴函式,p,r為下標

private

static

void

quicksortinternally

(int

arr,

int p,

int r)

int q =

paitition

(arr,p,r)

;// 獲取分割槽點

quicksortinternally

(arr,p,q-1)

;quicksortinternally

(arr,q+

1,r);}

private

static

intpartition

(int

arr,

int p,

int r)

else}}

int tmp = arr[i]

; arr[i]

= arr[r]

; arr[r]

= tmp;

system.out.

println

("i="

+ i)

;return i;

}}

效能分析

快速排序是穩定的演算法嗎?

不穩定,因為分割槽的過程涉及交換操作,如果陣列中有兩個相同的元素,比如序列 6,8,7,6,3,5,9,4,在經過第一次分割槽操作之後,兩個 6 的相對先後順序就會改變。所以,快速排序並不是乙個穩定的排序演算法。

空間複雜度是多少?

可以原地實現,所以是 o(1)

快排的時間複雜度?

每次選擇的pivot都很合適,基準值左右兩部分的值比較均勻,時間複雜度 o(nlogn)

分割槽極不平衡:可以用遞迴樹來分析,會退化到 o(n^2)

應用場景:和堆排序一樣適合對大規模資料、或者隨機數排序。

**對於挖坑法 和 hoare 的簡單小結 **

挖坑法從大到小排序:定義兩個變數 l 和 h 分別指向第乙個和最後乙個數,假設我們選擇第乙個數為坑,用 part 將這個數儲存,從 h 往前找大於 part 的數填坑,填完一次後 h 變成下乙個要填的坑,從 l 往後找小於 part 的數填 h 的坑,此時 l 又成了坑…整個過程記住,h 和 l 誰在做 ++ 或者 – 操作的那個數不變,停下的那一刻另外乙個指標的數被賦值(填坑)。(簡記,敵動我不動,敵不動我就變跟它一樣)。

hoare法從大到小排序:定義兩個變數 p 和 q 分別指向第乙個和最後乙個數,假設選擇第乙個數為分割槽點,q 從當前數往前找小於 arr[0] 的,找到後停止,p從 arr[1] 開始找大於 arr[0]

的,找到後 p 和 q 的數交換,直到 p 和 q 相遇,其中乙個數再和 arr[0] 交換。(p 和 q 遍歷過的地方都是滿足條件的)。

快速排序時間複雜度分析

為了分析快速排序的時間複雜度,請先看下面的主定理 主定理 t n at n b f n 其中 a 1 and b 1 是常量 並且 f n 是乙個漸近正函式,為了使用這個主定理,您需要考慮下列三種情況 快速排序的每一次劃分把乙個 問題分解成兩個子問題,其中的關係可以用下式表示 t n 2t n 2 ...

基於比較氣泡排序 時間複雜度O n 2

只操作相鄰的兩個資料,每次冒泡操作都會對相鄰的兩個元素進行比較,看是否滿足大小關係要求,如果不滿足讓它兩互換。一次冒泡會讓至少乙個元素移動到它應該在的位置,重複 n 次,就完成了 n 個資料的排序工作。eg 對於一組資料 4 5 6 3 2 1第一次冒泡的過程 經過了 5 次比較,此時 3 已經在正...

基於比較的插入排序 時間複雜度O n 2

直接插入排序 insert sort 將陣列中的資料分為兩個區域,已排序區間和未排序區間。初始已排序區間只有乙個元素,就是陣列的第乙個元素。插入演算法的核心思想就是取未排序區間中的元素,在已排序區間中從後往前找到最合適的位置將其插入,並保證已排序區間資料一直有序,重複這個過程,直到未排序區間中元素未...