可以通过改写快速排序算法解决
一趟排序划分出基准位置pivot
- pivot == k - 1,则pivot 位置数据就是
- pivot > k - 1,则在左半继续寻找
- pivot < k - 1,则在右半继续寻找
采用“三数取中”的方法选取划分标准。
代码是拿之前快速排序实验程序改的。
#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;
//三数取中划分法
int FindPivort(int i,int j,int A[])
{
int key=A[i];
for(int k=i+1;k<=j;k++)
{
if(A[k]!=key)
{
int mid =(i+j)/2;
int middle=A[i]>=A[mid]?(A[mid]>=A[j]?A[mid]:(A[i]>=A[j]?A[j]:A[i])):(A[i]>=A[j]?A[i]:(A[mid]>=A[j]?A[j]:A[mid]));
if(middle==A[i])
return i;
else if(middle==A[mid])
return mid;
else
return j;
}
}
return -1;
}
int Partition(int i,int j,int pivort,int A[])
{
int l=i,r=j;
while(1){
while(A[r]>=pivort&&r>l)
r--;
if(l<r)
{
A[l]=A[r];
}
while(A[l]<pivort&&r>l)
l++;
if(l<r)
{
A[r]=A[l];
}
if(r<=l)
break;
}
A[l]=pivort;
return l;
}
int Find_k(int i, int j,int A[],int key)
{
int pivort;
int k;
int pivortindex;
pivortindex=FindPivort(i,j,A);
if(pivortindex!=-1&&i<j)
{
if(pivortindex!=i)
swap(A[i],A[pivortindex]);
pivort = A[i];
k=Partition(i,j,pivort,A);
if(key==k)
return key;
else if(key<k)
return Find_k(i,k-1,A,key);
else
return Find_k(k+1,j,A,key);
}
}
int main()
{
int A[11];
for(int i=1;i<11;i++)
{
A[i]=i;
}
int index_k=Find_k(1,10,A,5);//查找第3小的元素
cout<<index_k<<endl;
return 0;
}
分析最好、最坏和平均时间复杂性:
1)最好时间复杂性:
最好情况是常数时间找到第k小的元素。
2)最坏时间复杂性:
最坏时间复杂性和划分基准元素的选取有关。
参考快速排序的时间复杂性,最坏时间复杂性为
3)平均时间复杂性:
待定。。。还没有想明白