看來編程技術還有待提高,尤其是一個思維模式要待提高。
前一個選擇,即隨機選擇一個數作爲分割點可能會造成最壞情況也爲O(n*n),當時的分析是在期望情況下以線性時間做選擇。本算法是在最壞情況下都是線性時間做選擇。主要的思想爲:
1.將長度爲n的數組按每5個元素做一組,當然最後可能有一組數據是沒有5個元素的。
2.將1得到的每組數據進行插入排序,從而找到每組中的中位數。
3.在2得到的每組中位數中也以這種將數組分成每組5個元素的形式找出這中位數的中位數x。
4.以x爲點劃分數組。
5.判斷劃分點是否爲我們所要的找的點,若是,算法結束,若在x以前的數目大於我們要尋找的k,則在x前面數據中找,否則在x的後面數據中找。
算法代碼實現如下:
//在最壞情況下以O(n)時間做選擇
#include<iostream>
using namespace std ;
bool failed = false ;
//這裏只考慮整型數
int selectMid(int *array, int start ,int end)
{
if(array == NULL || start > end )
{
failed = true ;
return 0 ;
}
failed = false ;
if(start == end )
{
return array[start] ;
}
if( start+1 == end )
{
return array[start] < array[end] ? array[start]:array[end];
}
//將數組分割成n/5個數組
int len = end - start + 1 ;
int partion = len / 5 ;
if(len % 5 != 0 )
{
partion ++ ;
}
int *mids = new int[partion];
for(int i = 0 ; i < partion ; i ++ )
{
//執行插入排序
int s = i*5 + start;
int e = (i+1)*5+start < end ? (i+1)*5+start:end+1 ;
int mid = (e-s)%2 == 1 ? (e-s)/2+1:(e-s)/2 ;
e-- ;
int temp = 0 ;
int p = s ;
for(int j = s+1; j <= e; j ++ )
{
// insert
int k = j ;
while(k > s )
{
if(array[k] < array[k-1])
{
temp = array[k] ;
array[k] = array[k-1] ;
array[k-1] = temp ;
k -- ;
}else
break ;
}
}
mids[i] = array[s+mid-1] ;
}
int x = selectMid(mids,0,partion-1);
delete []mids ;
return x ;
}
int select(int *array,int start, int end,int i )
{
if(array == NULL || start > end || i <= 0 || i > (end - start+1))
{
failed = true ;
return -1 ;
}
failed = false ;
int x = selectMid(array,start,end);
//對數組進行分組
int len = end - start + 1 ;
int tmp = 0 ;
int f = start ;
int tk = i ;
int samenum = 0 ;
for(int k = start ; k <= end ; k ++ )
{
if(array[k] < x)
{
tmp = array[k] ;
array[k] = array[f] ;
array[f] = tmp ;
f ++ ;
}else if(array[k] == x )//如果是有相等
{
tmp = array[k] ;
array[k] = array[f] ;
array[f] = tmp ;
f ++ ;
samenum ++ ;
}
}
if( (f-start) == i)
{
return array[f-1] ;
}
if( (f-start) > i )
{
end = f-2 ; //要將x去掉。
}else
{
i = i + start ;//這個地方出現過錯誤,就是邊界很難考慮周全了。
start = f ;
tk = i - start ;
}
x = select(array,start,end,tk);
return x ;
}
int main()
{
int array[10] = {1,2,3,9,5,6,7,8,9,9};
for(int i = 1 ; i<=10 ; i ++ )
cout<<select(array,0,9,i)<<endl;
system("pause");
return 0 ;
}