您的位置:首页 > 其它

算法之查找第k小的数和查找最小的k个元素

2013-05-22 14:01 246 查看
利用快速排序的思想查找第k小的数,主要的核心思想还是快速排序的分治算法,具体的思路是这样的:

1 利用快排的partion函数将数组分成左右两个部分,

2 如果p刚好等于k,则说明p位置的数,就是我们要找的数,如果分出来的边界位置p小于给定的数k,我们知道最小的第k个数,肯定在p的右边,如果p大于给定的k则在p边界的左边

3 递归在p的左边或者右边查找

注:p为数组下标需要加1,一般会使用随机数,即在数组中随机选取一个数作为每次分边界的值。

具体的细节可以查看《算法导论》第九章,下面是简单的实现代码,没有完全验证过;

/*
查找第k小的数
*/
#include <iostream>

using namespace std;

int partion(int array[],int s,int e)
{
int temp = array[s];
while(s < e)
{
while(array[e] >= temp&& s<e )
e--;
if(s < e)
array[s] = array[e];
while(array[s] < temp && s<e)
s++;
if(s < e)
array[e] = array[s];
}
array[s] = temp;
return s;
}

int search_k(int array[],int s,int e,int k)
{
int p = partion(array,s,e);
int q = p+1;
if( q == k )
return array[p];
if( q < k)
return search_k(array,p+1,e,k);
if( q > k)
return search_k(array,s,p-1,k);
}

int main()
{
int array[1000];
int n;
int k;
while( cin >> n >> k && n!=0)
{
for(int i=0;i<n;i++)
cin >> array[i];

cout << search_k(array,0,n-1,k) << endl;
}
}


查找最小的k个数,我用上面的方法肯定也是可以的,只需要将分界的p返回,p左边的数(包括p位置本身),就是我们需要的所有的最小的k个数,简单验证过,还可以维护一个集合数据的个数为k,每次从数组中取出一个数,如果集合中的数字的个数小于k,则认为集合中的所有数都是最小的k个数,如果集合中的的数据的个数大于k了,则每次将最大的数置换出来,遍历完数组之后,集合中的k个数就是最小的k个数的集合,用c++ 中的STL可以简单实现下面的代码:

#include <iostream>
#include <set>
#include <vector>

using namespace std;

typedef multiset<int,greater<int> > IntHeap;

void FindLeastKNum(vector<int> &ivec,
int k,
IntHeap &leastNum)
{
for(vector<int>::iterator iter= ivec.begin();
iter != ivec.end(); iter++)
{
//	cout << *iter  << " ";
if(leastNum.size() < k)
leastNum.insert(*iter);
else
{
IntHeap::iterator Tmpiter = leastNum.begin();	//
//		cout <<"the  biggest"<< *Tmpiter <<endl;
if(*iter < *Tmpiter)
{
leastNum.erase(Tmpiter);
leastNum.insert( *iter );
}

}
}
}

int main()
{
int n;
cin>> n ;
vector<int> ivec;
while(n--)
{
int num =0;
cin >> num;
ivec.insert(ivec.begin(),num);
}
int k;
cin >> k;
IntHeap leastNum;
FindLeastKNum(ivec,k,leastNum);

cout << "the  least k nums are: " <<endl;
for(IntHeap::iterator iter=leastNum.begin();
iter != leastNum.end(); iter++)
cout << *iter << " ";
cout <<endl;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐