找出给定数组或文件中最小的k个数

// 30 FindMinKNum.cpp : Defines the entry point for the console application.
//
/*****************************************************************************************************
*					找出数组中最小的K个数并输出
* 《剑指offer》面试题30:输入n个整数,找出其中最小的k个数。例如:输入4,5,1,6,2,7,3,8这8个数字,则最小的
   4个数字为1,2,3,4.
*  思路1:对数组按从小到大进行排序,最前面的K个数即为最小的K个数。时间复杂度O(nlogn)。
   思路2:利用快速排序的Partition函数,找出第k小的数a,我们知道此时第k小的数的左边均小于a,右边均大于a,
   此时,直接输出数组的前k个数即可。时间复杂度O(n),可以修改输入的数组时可用。此方法的实现参见上篇
   《在O(n)时间内找到数组中任意第k小的数》
   思路3:可以先创建一个大小为k的数据容器来存储最小的k个数字,接下来每次从输入的n个整数中读入一个数。
   如果容器中已有的数字少于k个,则直接把这次读入的数据放入容器之中;
   如果容器已满,找出容器中k个数字的最大值,然后拿这次待插入的整数与其进行比较。如果插入的值比当前已有
   的最大值大,那么这个数不可能是最小的k个整数之一,于是可以抛弃这个数。如果带插入的值小于当前已有最大
   数,则删除容易中已有的最大数,并插入这个带插入的值。重复上述过程。由于每次都需要找到k个整数中最大的
   数字,很容易想到利用最大堆来实现上述过程。
******************************************************************************************************/

#include "stdafx.h"
#include <iostream>
#include <string>
#include <fstream>
//#include <map>
#include <set>
using namespace std;


class Compare
{
public:
	bool operator()(const int& a, const int& b)
	{
		return (a-b)>0;
	}
};

bool FindMinKNum(ifstream& ifs, const int& k, multiset<int, Compare>& MinKNum);
bool FindMinKNum(int a[], const int& Len, const int& k, multiset<int, Compare>& MinKNum);

int _tmain(int argc, _TCHAR* argv[])
{
	/*map<string, int> students;
	pair<string, int> stu1;
	pair<string, int> stu2;

	stu1 = make_pair("li", 80);
	stu2 = make_pair("chen", 70);

	students.insert(stu1);
	students.insert(stu2);

	map<string, int>::iterator  i;
	for(i=students.begin(); i!=students.end(); i++)
		cout<<(*i).first<<" "<<(*i).second<<endl;*/
	/*
	int a[] = {4,5,1,6,2,7,3,8};
	multiset<int, Compare> MinKNum;
	multiset<int, Compare>::iterator IterBeg;
	multiset<int, Compare>::iterator IterEnd;

	FindMinKNum(a, 8, 4, MinKNum);
	IterBeg = MinKNum.begin();
	IterEnd = MinKNum.end();
	for(; IterBeg!=IterEnd; IterBeg++)
		cout<<(*IterBeg)<<" ";
	*/
	ifstream ifs(_T("data.txt"));
	multiset<int, Compare> MinKNum;
	multiset<int, Compare>::iterator IterBeg;
	multiset<int, Compare>::iterator IterEnd;

	FindMinKNum(ifs, 10, MinKNum);
	IterBeg = MinKNum.begin();
	IterEnd = MinKNum.end();
	for(; IterBeg!=IterEnd; IterBeg++)
		cout<<(*IterBeg)<<" ";
	while(true);
	return 0;
}

/**************************************************************************************
* Author:			        sky	
* Functiuon:				FindMinKNum
* Description:				找出给定文件中最小的k个数      
* Access Level:			NULL
* Input:                               ifs:输入文件流
				        k:  最小的k个数
* Output:			        MinKNum:存储找出的最小的k个数        
* Return:			        false/true       
**************************************************************************************/
bool FindMinKNum(ifstream& ifs, const int& k, multiset<int, Compare>& MinKNum)
{
	multiset<int, Compare>::iterator iter;
	int data;							        //	存储每次从文件读取到的数据
	int count = 0;								//	记录muliset中元素的个数
	
	ifs>>data;
	while(ifs.good())
	{
		if(k > count)
		{
			MinKNum.insert(data);
			count++;
		}
		else
		{
			iter = MinKNum.begin();
			if((*iter) > data)
			{
				MinKNum.erase(iter);
				MinKNum.insert(data);
			}
		}
		ifs>>data;
	}
	return true;
}

/**************************************************************************************
* Author:					sky	
* Functiuon:				FindMinKNum
* Description:				找出给定数组中最小的k个数      
* Access Level:			NULL
* Input:                               a:  输入数组
				        k:  最小的k个数
* Output:			        MinKNum:存储找出的最小的k个数        
* Return:			        false/true       
**************************************************************************************/
bool FindMinKNum(int* a, const int& Len, const int& k, multiset<int, Compare>& MinKNum)
{

	if((NULL==a) || (k>Len))
		return false;

	multiset<int, Compare>::iterator iter;
	int i = 0;			

	for(i=0; i!=Len; i++)
	{
		if(i < k)
			MinKNum.insert(a[i]);
		else
		{
			iter = MinKNum.begin();
			if((*iter) > a[i])
			{
				MinKNum.erase(iter);
				MinKNum.insert(a[i]);
			}
		}
	}
	return true;
}

输入文件:


输出结果:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值