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

 

         利用快速排序的思想查找第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;
}

    原文作者:查找算法
    原文地址: https://blog.csdn.net/qingtianweichong/article/details/8960067
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞