資料結構與演算法C 之快速排序(續)

2021-08-31 09:46:19 字數 3826 閱讀 9651

(一)對於近乎有序的陣列,演算法的計算複雜度由o(nlogn)退化到o(n2)

使用上篇部落格裡的快速排序演算法做測試,測試程式為

int

main()

測試結果

可以看出對於乙個近乎有序的5萬個元素的陣列,快速排序用了 0.545s,比歸併排序慢了很多倍快速排序演算法中,我們一般將陣列最左邊的元素作為參考元素,這樣的話,當陣列近乎有序的時候,對整個陣列進行partition後,左邊小於參考元素的個數會很少,近乎沒有,右邊大於參考元素的個數將會接近整個陣列元素個數,在遞迴過程中,每層的partition都將近乎只有一部分,如下圖所示

解決方案很簡單,就是隨機選取參考元素,具體實現如下

#include

#ifndef _sortinghelp_h_

#define _sortinghelp_h_

#include

"sortinghelp.h"

#endif

// _sortinghelp_h_

#include

"mergesorting.h"

using namespace std;

//對arr[l...r]進行partition操作

//返回p,使得arr[l...p-1] < arr[p]; arr[p+1...r] > arr[p]

template

int__partition

(t arr,

int l,

int r)

}swap

(arr[l]

, arr[j]);

return j;

}//對arr[l...r]部分進行排序

template

void

__quicksorting

(t arr,

int l,

int r)

template

void

quicksorting

(t arr,

int n)

intmain()

輸出為

隨機設定參考元素後,對於近乎有序的陣列,快速排序演算法的速度恢復正常了

(二)如果陣列中存在大量重複的元素,那麼演算法的計算複雜度也會退化到o(n2)

首先測試一下當陣列中有大量重複元素時,演算法的執行時間

int

main()

輸出為

可以看出使用上面隨機設定參考元素的方法,計算時間還是很長

由下圖可以看出,當存在大量重複元素時,還是會出現partition後左右不平衡的現象

在上篇部落格的演算法中遍歷陣列元素時是從左到右依次遍歷,遇到大於參考元素的值不操作,遇到小於參考元素的值將其與第乙個大於參考元素的值相交換,下面換一種策略

如上圖所示,同時從陣列兩邊進行遍歷,首先還是隨機設定乙個參考元素 v

vv,然後與最左邊元素進行位置交換

(1)索引為 i

ii 的元素從左向右遍歷,如果遍歷的元素小於 v

vv ,那麼就繼續遍歷,如果大於等於 v

vv ,那麼就停止

(2)此時索引為 j

jj 的元素從右向左遍歷,如果遍歷的元素大於 v

vv ,那麼就繼續遍歷,如果小於等於 v

vv ,那麼就停止

(3)將索引為 i

ii 的元素與索引為 j

jj 的元素交換位置,此時左右兩邊又都符合條件了, i

ii 和 j

jj 就繼續開始遍歷

這樣的話,即使有大量重複的元素,也會不斷交換分散到左右兩邊(i

ii 和 j

jj 交換時有三種可能,一、i

ii 和 j

jj 都等於 v

vv ;二、i

ii 等於 v

vv, j

jj 不等於 v

vv ;三、i

ii 不等於 v

vv, j

jj 等於 v

vv),不會出現左右不平衡的現象

上述改進原理也可檢視部落格

實現程式如下

#include

#ifndef _sortinghelp_h_

#define _sortinghelp_h_

#include

"sortinghelp.h"

#endif

// _sortinghelp_h_

#include

"mergesorting.h"

using namespace std;

//對arr[l...r]進行partition操作

//返回p,使得arr[l...p-1] < arr[p]; arr[p+1...r] > arr[p]

template

int__partition

(t arr,

int l,

int r)

}swap

(arr[l]

, arr[j]);

return j;

}//對arr[l...r]部分進行排序

template

void

__quicksorting

(t arr,

int l,

int r)

template

void

quicksorting

(t arr,

int n)

//下面是改進後的快速排序演算法

//對arr[l...r]進行partition操作

//返回p,使得arr[l...p-1] < arr[p]; arr[p+1...r] > arr[p]

template

int__partition2

(t arr,

int l,

int r)

swap

(arr[l]

, arr[j]);

return j;

}//對arr[l...r]部分進行排序

template

void

__quicksorting2

(t arr,

int l,

int r)

template

void

quicksorting2

(t arr,

int n)

intmain()

輸出為

可以看出使用左右兩個方向都遍歷,已經可以對有大量重複元素的陣列進行快速排序

資料結構與演算法之快速排序

1.快速排序的 實現如下 include using namespace std template void sort t data,size t head,size t tail templatesize t partition t data,size t head,size t tail tem...

資料結構與演算法之快速排序

快速排序是c.r.a.hoare於1962年提出的一種劃分交換排序。它採用了一種分治的策略,通常稱其為分治法 divide and conquermethod 該方法的基本思想是 1 先從數列中取出乙個數作為基準數。2 分割槽過程,將比這個數大的數全放到它的右邊,小於或等於它的數全放到它的左邊。3 ...

資料結構與演算法 排序演算法之六 快速排序

一 快速排序 排序演算法中的奧斯卡,諾貝爾獎,當屬快速排序!快速排序是20世紀十大演算法之一!1 基本思想 前面提到氣泡排序,它是一種交換排序,堪稱最慢的排序演算法。可是,物極必反,快速排序是氣泡排序的公升級加強版,同屬於交換排序類。以 空間 換時間,快速排序不是相鄰元素的交換,而是加大了比較和交換...