【題目】
在n個元素的無序陣列中選擇第k(1<=k<=n)小元素。
當k=1時,相當於找最小值。
當k=n時,相當於找最大值。
當k=n/2時,稱中值。
【要求】
線性時間內完成,即o(n)。
【演算法解析】
通過執行下列步驟,演算法select可以確定乙個有n>1個不同元素的輸入陣列中第i小的元素。(如果n=1,則select只返回它的唯一輸入數值作為第i小的元素。)
1、將輸入陣列的n個元素劃分為⌈n/5⌉組,每組5個元素,且至多有乙個組由剩下的n mod 5個元素組成。
2、尋找這⌈n/5⌉組中每一組的中位數:首先對每組元素進行插入排序(我這裡用的是改進版的氣泡排序),然後確定有序元素的中位數。
3、對第2步中找出的⌈n/5⌉個中位數,遞迴呼叫select找出其中位數x。(如果有偶數個中位數,為了方便,約定x是較小的中位數)。
4、利用修改過的partition過程,按中位數的中位數x對輸入陣列進行劃分。讓k比劃分低區的元素多1,因此x是第k小的元素,並且有n-k個元素在劃分的高區。
5、如果i=k,則返回x,否則,如果ik,則在高區遞迴查詢第(i-k)小的元素。
【核心**】
templatetype【完整**】select (type a,int p, int r, int
k)
//找中位數的中位數,r-p-4即上面所說的n-5
for ( int i = 0; i<=(r-p-4)/5; i++)
//獲取中位數的中位數
type x = select(a,p, p+(r-p-4)/5, (r-p-4)/10
);
//根據x劃分序列 ,i中位數的中位數所在下標
int i=partition(a,p,r,x);
//j是中位數的中位數的序數
int j=i-p+1
;
if (k<=j) return
select
(a,p,i,k);
else
return
select(a,i+1,r,k-j);
}
#include using【時間複雜度】namespace
std;
//交換函式
template
void swap(type a,int p,int
r)//
改進版氣泡排序
template
void bubblesort(type a,int p,int
r)
}break
; }}//
冒泡操作
template
void bubble(t a,int p, intr)}
//劃分函式
template
int partition (t a, const
int p, const
intr,t x)
}return
pivotpos;
}template
type
select (type a,int p, int r, int
k)
//找中位數的中位數,r-p-4即上面所說的n-5
for ( int i = 0; i<=(r-p-4)/5; i++)
//獲取中位數的中位數
type x = select(a,p, p+(r-p-4)/5, (r-p-4)/10
);
//根據x劃分序列 ,i中位數的中位數所在下標
int i=partition(a,p,r,x);
//j是中位數的中位數的序數
int j=i-p+1
;
if (k<=j) return
select
(a,p,i,k);
else
return
select(a,i+1,r,k-j);
}int
main() ;
//int a=;
int a=;
cout
<
);
return0;
}
最壞情況為線性時間的選擇演算法
輸入 一系列數a 0 a n 1 和乙個整數k 輸出 這列數中第k小的數 同樣的問題在上篇文章中用快速排序模型,我們得到的平均時間複雜度是o n 但是遺憾的是最壞情況會達到o n 2 這篇文章中我們還是使用快速排序的模型,但是改變了劃分的方式,這個演算法會保準得到乙個很好的劃分。將該演算法叫做sel...
最壞情況線性時間選擇O n
題目 給定線性序集中n個元素和乙個整數k,1 k n,要求找出這n個元素中第k小的元素,這裡給定的線性集是無序的 具體解題 這裡我們將所有的數 n個 以每5個劃分為一組,共 n 5 組 將不足五個的那組忽略 然後用任意一種排序演算法 因為只對五個數進行排序,所以任取一種排序法就可以了,這裡我選用氣泡...
最差情況為線性時間的選擇
這個演算法寫了我好久,在這裡記一下。演算法的原理是利用中位數來作為劃分元素選擇第m小的元素,中位數需要遞迴自身來求得。演算法的最優,平均,最差時間複雜度都為o n 相對於隨機演算法改善了最差時間複雜度。和快排用了同樣的partition,但是這個演算法所使用的pivot是確定的,即中位數。版本為go...