1. 程式人生 > >查詢最小的k個元素-快排、中位數選擇(上)

查詢最小的k個元素-快排、中位數選擇(上)

查詢最小的k個元素(陣列)
題目:輸入n個整數,輸出其中最小的k個。
例如輸入1,2,3,4,5,6,7和8這8個數字,則最小的4個數字為1,2,3和4。

//coder:LEE

//20120304
#include<iostream>
#include<CASSERT>
#include <ctime>
#include <CWINDOW.H>
using namespace std;
//陣列b中儲存前k個值,然後遍歷陣列a,將b中最大的值用a中小於他的值替換
//時間複雜度:o(n-k^2+k)
void MinK(int* a,int n,int k)
{
assert(a!=NULL&&k>0&&n>0);
int* b=new int[k];
for(int i=0;i<k;i++)
b[i]=a[i];
for (;i<n;i++)
{
int max=b[0];
int maxTag=0;
for (int j=1;j<k;j++)
{
if (b[j]>max)
{
max=b[j];
maxTag=j;
}
}
if(a[i]<max)
b[maxTag]=a[i];
}
//for(i=0;i<k;i++)
//cout<<b[i]<<"  ";
//cout<<endl;
}
void Swap(int *a,int *b)
{
int t=*a;
*a=*b;
*b=t;
}
int Partition(int *A,int p,int r)
{
int x=A[r];
int i=p-1;
for (int j=p;j<=r-1;j++)
{
if (A[j]<=x)
{
i+=1;
Swap(&A[i],&A[j]);
}
}
Swap(&A[i+1],&A[r]);
return i+1;
}
void QuickSort(int *A,int p,int r)//快速排序
{
if(p<r)
{
int q=Partition(A,p,r);
QuickSort(A,p,q-1);
QuickSort(A,q+1,r);
}
}
int RandomizedPartition(int *A,int p,int r)
{
srand(time(0));
int randNumber=rand()%(r-p+1)+p;
Swap(&A[randNumber],&A[r]);
return Partition(A,p,r);
}
void RandomizedQuickSort(int *A,int p,int r)
{
if(p<r)
{
int q=RandomizedPartition(A,p,r);
RandomizedQuickSort(A,p,q-1);
RandomizedQuickSort(A,q+1,r);
}
}
void RandomizedSelect(int *A,int p,int r,int i)//時間複雜度O(n)
{
if(p==r)
return;
int q=RandomizedPartition(A,p,r);
int k=q-p+1;
if(i==k)
return;
else if(i<k)
RandomizedSelect(A,p,q-1,i);
else
RandomizedSelect(A,q+1,r,i-k);


}


void InsertionSort(int *A,int p,int r)//插入排序
{
for (int j=p+1;j<=r;j++)
{
int key=A[j];
int i=j-1;
while(i>=p&&A[i]>key)
{
A[i+1]=A[i];
i=i-1;
}
A[i+1]=key;
}
}
int MedianFind(int *A,int p,int r)//選擇中位數的中位數
{
int groups=(r-p)/5+1;
int remains=(r-p+1)-5*(groups-1);
int *median=new int[groups];
for(int i=0;i<groups;i++)
{
if (i!=groups-1)
{
InsertionSort(A,p+5*i,p+5*i+4);
median[i]=A[p+5*i+2];
}
else
{
InsertionSort(A,p+5*i,p+remains-1);
median[i]=A[p+5*i+remains/2];
}
}
//cout<<"groups;"<<endl;
//for(i=0;i<groups;i++)
//cout<<median[i]<<"  ";
//cout<<endl;
if(groups==1)
return median[0];
else
return MedianFind(median,0,groups-1);
return 0;
}
int MedianPartition(int *A,int p,int r,int n)
{
Swap(&A[n],&A[r]);//交換
return Partition(A,p,r);
}
void MedianSelect(int *A,int p,int r,int i)

if(p==r)
return;
int median=MedianFind(A,p,r);
for(int j=p;j<=r;j++)
if(median==A[j])//找到中位數的標號
break;
int q=MedianPartition(A,p,r,j);
int k=q-p+1;
if(i==k)
return;
else if(i<k)
MedianSelect(A,p,q-1,i);
else
MedianSelect(A,q+1,r,i-k);
}
int main()
{
const numbers=100000;
int data[numbers];
for (int i=0;i<numbers;i++)
{
data[i]=rand()%numbers;
}
cout<<"after:"<<endl;
double beg=GetTickCount();
MedianSelect(data,0,sizeof(data)/sizeof(int)-1,100);
double end=GetTickCount();
cout<<"time:"<<(end-beg)<<"ms"<<endl;
//for (i=0;i<sizeof(data)/sizeof(int);i++)
//cout<<data[i]<<" ";



/*int a1[]={2,8,7,1,3,5,6,4};
InsertionSort(a1,0,sizeof(a1)/sizeof(int)-1);
for (int j=0;j<sizeof(a1)/sizeof(int);j++)
{
cout<<a1[j]<<" ";
}


cout<<endl;
int data[100];
for (int i=0;i<100;i++)
{
data[i]=rand()%100;
}
RandomizedSelect(data,0,sizeof(data)/sizeof(int)-1,11);
for (i=0;i<sizeof(data)/sizeof(int);i++)
{
cout<<data[i]<<" ";
}
cout<<endl;


int a2[]={2,8,7,1,3,5,6,4};
RandomizedQuickSort(a2,0,sizeof(a2)/sizeof(int)-1);
for (int j=0;j<sizeof(a2)/sizeof(int);j++)
{
cout<<a2[j]<<" ";
}

int a1[]={1,2,3,4,5,6,7,8};
int k1=4;
MinK(a1,sizeof(a1)/sizeof(int),k1);
*/
return 0;
}