一、題目
要在n個數中選出第i個順序統計量,select在最壞情況下需要的比較次數t(n)滿足t(n)=θ(n)。但是,隱含在θ記號中的常數項是非常大的。當i相對n來說很小時,我們可以實現乙個不同的演算法,它以select作為子程式,但在最壞情況下,所做的比較次數更少。
a.設計乙個能用u
i(n)次比較在n個元素中找出第i小元素的演算法,其中,
(⌊n/2⌋個不相交的對的兩兩比較開始,然後對由每對中的較小元素構成的集合進行遞迴。)
二、解題思路
假設輸入陣列為a[p],a[p+1],...,a[p+n-1],共n個數
1、首先,取m=
⌊n/2
⌋,將輸入陣列進行劃分,第一組第1...m個數,第二組為第m+1...2m個數,如果n為奇數,還會多乙個數未分組a[2m+1].
2、分別對兩部分的第j個數進行比較(0≤j≤m
),就是a[p]和a[p+m],a[p+1]和a[p+m+1],...,如果a[p+j]a[p+m+j],較大元素放到a[p+j]。
3、對a[p+m]...a[p+n-1]遞迴執行1、2,這裡要注意,如果遞迴中對兩個分組的元素進行調換,那麼他們上一層分組左側組相應位置也得調換,依次類推,上上層以及更多層的相應位置都得調換,保證每個分組左側一組依次大於右側一組。
拿上圖來說,將12個元素劃分為藍色與紅色兩部分,分別比較aj和bj(j=1...6),小的放到bj裡,然後再對紅色部分劃分為兩部分,如果b4>b1,交換b4與b1,同時交換a4與a1,交換後元素大小如箭頭所示。再對紅色右半部分劃分,如果b4
4、每遞迴一次,分組就減少一半,當i大於等於分組元素個數的一半時,停止遞迴,採用select方法對最後分組l劃分,此時l前i個數是該分組最小的i個數,倒數第二個分組l1元素依次大於l,那麼l和l1的第i小數就在l的前i個數和l1的前i個數之中,利用select對這2i個數操作(如果n為奇數,就將最後乙個數也加進去),找到這兩分組前i小的數,返回上一層呼叫當中。
5、在上一層呼叫中,用select對左右分組前i個數共2i個數操作,然後再返回,直到頂層。
三、偽**如下:(select()為9.3節最壞情況線性時間選擇演算法,與書中稍有不同,這裡需要同時交換各層次分組相同位置的元素)
s_select(a,p,r,i,g)
n = r-p+1;
if i>=n/2
select(a,p,r,i,g)//▲
else
m = ⌊n/2⌋
g=m;//陣列g儲存各次分組的大小
for j=0 to m-1
if a[p+j] < a[p+m+j]
exchange(a[p+j],a[p+m+j])//▲
s_select(a,p+m,r,g)
b=array()
for j=1 to i
b[j] = a[p+j-1]
b[j+i]=a[p+m+j-1]
if n is odd//如果n是奇數,那麼最後會多出來一項
b[2i+1] = a[p-1+n]
b = select(b,1,2i+1,i)
else b = select(b,1,2i,i)//此時b[1]...b[i]是b前i小的數
a[p]...a[p+i-1] = b[1]...b[i]//▲
return a[p+i-1]
加黑色三角處需要
同時交換各層次分組相同位置的元素,寫起來比較複雜,**中沒有體現出來。
演算法導論 思考題 4 3
a.利用主方法可得,t n n的log3 4次方 b.n f n lgn,不能應用主方法 共log3 n 1層,每層代價n lg n 3 的i次方 最後一層共n個 1 的結點,代價為 n t n n lg n 3 的i次方 n n lgn n n log3 2 n o n 又因為t n 最後一層代價...
演算法導論 思考題 8 4
寫一下我的思路,大概是對的,詳細證明不出來。設藍色水壺為a,紅色為b 先取乙個a1,對所有的b做一次比較,可以將b分為兩個部分,一部分大於a1,一部分小於a1 再取乙個a2,將b分為三個部分 再取a3,將b分為四個部分 假設現在b被分成了k個部分,b1,b2,b3.bk,每次取ai,都從b集合的一半...
演算法導論 思考題 4 5
這題實在沒什麼思路,網上找了一下答案。如果一開始就能夠確定好的晶元多於壞的,則可以保證每輪檢測結束好的晶元都多於壞的,一直到最後如果剩2塊晶元,則兩塊肯定都是好的 剩3塊晶元就再檢測一次,如果結果都是好的,就隨意取一片必定是好的 如果結果都是壞的,則剩下的那塊肯定是好的。來證明一下上面的結論 設有x...