分治法 快速排序 歸併排序 堆排序

2021-09-09 07:57:35 字數 2479 閱讀 9796

十種常見排序演算法可以分為兩大類:

**非線性時間比較類排序:**通過比較來決定元素間的相對次序,由於其時間複雜度不能突破o(nlogn),因此稱為非線性時間比較類排序。

**線性時間非比較類排序:**不通過比較來決定元素間的相對次序,它可以突破基於比較排序的時間下界,以線性時間執行,因此稱為線性時間非比較類排序。

0.2 演算法複雜度

0.3 相關概念

穩定:如果a原本在b前面,而a=b,排序之後a仍然在b的前面。

不穩定:如果a原本在b的前面,而a=b,排序之後 a 可能會出現在 b 的後面。

時間複雜度:對排序資料的總的操作次數。反映當n變化時,操作次數呈現什麼規律。

空間複雜度:是指演算法在計算機內執行時所需儲存空間的度量,它也是資料規模n的函式。

下面主要看三種排序方法:

1、快速排序

假設我們現在對「6 1 2 7 9 3 4 5 10 8」這個10個數進行排序。首先在這個序列中隨便找乙個數作為基準數(不要被這個名詞嚇到了,就是乙個用來參照的數,待會你就知道它用來做啥的了)。為了方便,就讓第乙個數6作為基準數吧。接下來,需要將這個序列中所有比基準數大的數放在6的右邊,比基準數小的數放在6的左邊,類似下面這種排列:

3 1 2 5 4 6 9 7 10 8

在初始狀態下,數字6在序列的第1位。我們的目標是將6挪到序列中間的某個位置,假設這個位置是k。現在就需要尋找這個k,並且以第k位為分界點,左邊的數都小於等於6,右邊的數都大於等於6,遞迴對左右兩個區間進行同樣排序即可。想一想,你有辦法可以做到這點嗎?這就是快速排序所解決的問題。

快速排序是c.r.a.hoare於2023年提出的一種劃分交換排序。它採用了一種分治的策略,通常稱其為分治法(divide-and-conquermethod)。它的平均時間複雜度為o(nlogn),最壞時間複雜度為o(n^2).

首先上圖:

left指標,right指標,base參照數。

其實思想是蠻簡單的,就是通過第一遍的遍歷(讓left和right指標重合)來找到陣列的切割點。

第一步:首先我們從陣列的left位置取出該數(20)作為基準(base)參照物。(如果是選取隨機的,則找到隨機的哨兵之後,將它與第乙個元素交換,開始普通的快排)

第二步:從陣列的right位置向前找,一直找到比(base)小的數,如果找到,將此數賦給left位置(也就是將10賦給20),此時陣列為:10,40,50,10,60, left和right指標分別為前後的10。

第三步:從陣列的left位置向後找,一直找到比(base)大的數,如果找到,將此數賦給right的位置(也就是40賦給10),此時陣列為:10,40,50,40,60, left和right指標分別為前後的40。

第四步:重複「第二,第三「步驟,直到left和right指標重合,最後將(base)放到40的位置, 此時陣列值為: 10,20,50,40,60,至此完成一次排序。

第五步:此時20已經潛入到陣列的內部,20的左側一組數都比20小,20的右側作為一組數都比20大, 以20為切入點對左右兩邊數按照"第一,第二,第三,第四"步驟進行,最終快排大功告成。

快速排序**如下:

//快速排序,隨機選取哨兵放前面

void quicksort(int* h, int left, int right)

temp[k++]=arr[j++];

}while(i<=mid)

temp[k++]=arr[i++];

while(j<=right)

temp[k++]=arr[j++];

memcpy(&arr[left],temp,k*sizeof(int));

return;void mmergesort(int* arr, size_t left, size_t right, int* temp)

進行排序(降序):

首先要先建小堆:

堆建好了下來就要開始排序了:

現在這個陣列就已經是有序的了。

演算法實現:

//堆排序

/*大頂堆sort之後,陣列為從小到大排序

///調整

=void adjustheap(int h, int node, int len) //----node為需要調整的結點編號,從0開始編號;len為堆長度

//建堆

=void makeheap(int* h, int len)

//排序

=void heapsort(int* h, int len)

**

演算法 分治法 快速排序,歸併排序

分治法,是演算法思想裡最基礎的思想。這也和人的基本思維有關,當我們需要解決乙個大的問題時,直覺的就會將這個大問題分成多個小問題來解決。大量的經典演算法,都是基於分治法。比如,快速排序,歸併排序。當然,最讓人想起來的,就是二分查詢了。分治,分而治之。分的原因是因為問題的規模太大,需要拆開了解決,目的是...

快速排序 堆排序 歸併排序

快速排序 includeusing namespace std int a 8 int sz sizeof a sizeof int int partition int a,int p,int r int main const int sz sizeof a sizeof int 堆化 保持最大堆的...

快速排序,歸併排序,堆排序

l r 1在奇數長度陣列的中間,偶數長度陣列的左半邊最後乙個,極限情況下陣列只有兩個數,i遇到第乙個數就會停下,此時模擬i,j下標的數有無交換的情況,會發現j在停下來時都位於第乙個數的位置,因此用j,j 1才不會越界 l r 1 1在奇數長度陣列的中間往右第乙個,偶數長度陣列的右半邊第乙個,極限情況...