開開心心學演算法 快速排序之會場安排問題

2021-06-08 08:55:35 字數 2419 閱讀 3403

快速排序使用分治法(divide and conquer)策略來把乙個序列(list)分為兩個子串行(sub-lists)。

步驟為:

從數列中挑出乙個元素,稱為 "基準"(pivot),

重新排序數列,所有元素比基準值小的擺放在基準前面,所有元素比基準值大的擺在基準的後面(相同的數可以到任一邊)。在這個分割槽退出之後,該基準就處於數列的中間位置。這個稱為分割槽(partition)操作。

遞迴地(recursive)把小於基準值元素的子數列和大於基準值元素的子數列排序。

遞迴的最底部情形,是數列的大小是零或一,也就是永遠都已經被排序好了。雖然一直遞迴下去,但是這個演算法總會退出,因為在每次的迭代(iteration)中,它至少會把乙個元素擺到它最後的位置去。

快速排序是

二叉查詢樹

(二叉查詢樹)的乙個空間優化版本。不以循序地把專案插入到乙個明確的樹中,而是由快速排序組織這些專案到乙個由遞迴呼叫所意含的樹中。這兩個演算法完全地產生相同的比較次數,但是順序不同。

從一開始快速排序平均需要花費o(n log n)時間的描述並不明顯。但是不難觀察到的是分割槽運算,陣列的元素都會在每次迴圈中走訪過一次,使用o(n)的時間。在使用結合(concatenation)的版本中,這項運算也是o(n)。

在最好的情況,每次我們執行一次分割槽,我們會把乙個數列分為兩個幾近相等的片段。這個意思就是每次遞迴呼叫處理一半大小的數列。因此,在到達大小為一的數列前,我們只要作 log n 次巢狀的呼叫。這個意思就是呼叫樹的深度是o(log n)。但是在同一層次結構的兩個程式呼叫中,不會處理到原來數列的相同部份;因此,程式呼叫的每一層次結構總共全部僅需要o(n)的時間(每個呼叫有某些共同的額外耗費,但是因為在每一層次結構僅僅只有o(n)個呼叫,這些被歸納在o(n)係數中)。結果是這個演算法僅需使用o(n log n)時間。

另外乙個方法是為t(n)設立乙個遞迴關係式,也就是需要排序大小為n的數列所需要的時間。在最好的情況下,因為乙個單獨的快速排序呼叫牽涉了o(n)的工作,加上對n/2大小之數列的兩個遞迴呼叫,這個關係式可以是:

t( n) = o(

n) + 2t(

n/2)

解決這種關係式型態的標準數學歸納法技巧告訴我們t(n) = o(n log n)。

事實上,並不需要把數列如此精確地分割槽;即使如果每個基準值將元素分開為 99% 在一邊和 1% 在另一邊,呼叫的深度仍然限制在 100log n,所以全部執行時間依然是o(n log n)。

然而,在最壞的情況是,兩子數列擁有大各為 1 和 n-1,且呼叫樹(call tree)變成為乙個 n 個巢狀(nested)呼叫的線性連串(chain)。第 i 次調用作了o(n-i)的工作量,且

t( n) = o(

n) + t(1) + t(

n - 1) = o(

n) + t(

n - 1)

這與插入排序和選擇排序有相同的關係式,以及它被解為t(n) = o(n2)。

以上是理論,下面是乙個例項--會場安排問題,題目如下:

描述學校的小禮堂每天都會有許多活動,有時間這些活動的計畫時間會發生衝突,需要選擇出一些活動進行舉辦。小劉的工作就是安排學校小禮堂的活動,每個時間最多安排乙個活動。現在小劉有一些活動計畫的時間表,他想盡可能的安排更多的活動,請問他該如何安排。 輸入

第一行是乙個整型數m(m<100)表示共有m組測試資料。

每組測試資料的第一行是乙個整數n(1

輸出對於每一組輸入,輸出最多能夠安排的活動數量。

每組的輸出佔一行

樣例輸入

2

21 10

10 11

31 10

10 11

11 20

樣例輸出

1

2

提示

注意:如果上乙個活動在t時間結束,下乙個活動最早應該在t+1時間開始

在這個題目中,對排序的要求很高,一般的如氣泡排序是通不過的,因為他的時間限制為:

3000

ms。下面是我的解,我選擇的是快速排序演算法。

#include #include typedef struct party_timeparty;

//快速排序演算法 引數: a:陣列 l:左邊起始點 h:右邊起始點

void quicksort(party a,int l,int h)

{ if(l>=h)

return;

int j,i;

party key;

i=l;j=h;

key.start_time=a[i].start_time; //給參考點賦值

key.end_time=a[i].end_time;

while(ikey.end_time) ) //直到在右邊找到比參考值小的

j--;

if (i

開開心心學演算法 排序演算法

歸併排序 快速排序 堆排序思路 對於乙個序列為1,a2,an 的序列而言,1 是有序序列,而2,an 為待排序序列 那麼先抽出a2,讓key a2,這一步的目的是防止當a1往後移動的時候a2被覆蓋掉 然後讓a1與a2比較,如果a1 a2,則保持a2的位置不變 否則將a1向後移動一位,那麼此時a1就在...

開開心心學演算法 一種排序

時間限制 3000 ms 記憶體限制 65535 kb 難度 3 描述 現在有很多長方形,每乙個長方形都有乙個編號,這個編號可以重複 還知道這個長方形的寬和長,編號 長 寬都是整數 現在要求按照一下方式排序 預設排序規則都是從小到大 1.按照編號從小到大排序 2.對於編號相等的長方形,按照長方形的長...

開開心心學演算法 一種排序

時間限制 3000ms 記憶體限制 65535kb 難度 3 描述 現在有很多長方形,每乙個長方形都有乙個編號,這個編號可以重複 還知道這個長方形的寬和長,編號 長 寬都是整數 現在要求按照一下方式排序 預設排序規則都是從小到大 1.按照編號從小到大排序 2.對於編號相等的長方形,按照長方形的長排序...