大数据排序相关

1、1亿个整数排序。

主要有两种方法,一种是利用归并进行外部排序,思想如下:

(1)将文件中的数据按固定长度读入内存数组中,快排后,存入不同的文件中。

(2)同时打开这些文件,读入第一个到临时数组中,找最小的数,若找到,则对应的文件读下一个。

(3)若当前文件读完,在标志数组位置置为false.

(4)直到所有标志都为false循环结束。

代码如下:

#include <iostream>
#include<fstream>
using namespace std;
const int dataSize=5;
int compare(const void *num1,const void *num2)
{
	return *(int*)num1-*(int*)num2;
}
int main()
{  
	
	ifstream in("data.txt");
	int a[dataSize];
	int count=0;
	int fileNum=0;
	char fileName[20];
	ofstream out;
	while(in>>a[count])	//读完之后自动移到下一个位置
	{
		count++;
		if(count==dataSize || in.cur==in.eof())//表示数组已满//或者是最后一个数了
		{
			fileNum++;
			qsort(a,count,sizeof(int),compare);
			sprintf(fileName,"%d.txt",fileNum);//显得更加简洁
			out.open(fileName);
			for(int i=0;i<count;i++)
				out<<a[i]<<" ";
			out<<endl;			
			out.close();
			count=0;
		}
		
	}	
	in.close();
	//k路合并
	ifstream *inFile=new ifstream[fileNum];
	out.open("result.txt");
	int *tempDataArray=new int[fileNum];//存储数字
	bool *hasNextFlag=new bool[fileNum];//存储是否有下一个的标志
	for(int i=0;i<fileNum;i++)
	{
		sprintf(fileName,"%d.txt",i+1);
		inFile[i].open(fileName);
		inFile[i]>>tempDataArray[i];
		hasNextFlag[i]=true;
	}
	bool hasDataFlag=true;
	while(hasDataFlag)
	{
		int minData=0x7FFFFFFF,minSn;
		hasDataFlag=false;
		for(int i=0;i<fileNum;i++)
		{
			if(hasNextFlag[i]&&tempDataArray[i]<minData)
			{
				minData=tempDataArray[i];
				minSn=i;	
				hasDataFlag=true;
			}
		}
		if(hasDataFlag)
		{
			out<<minData<<" ";
			if(!(inFile[minSn]>>tempDataArray[minSn]))
				hasNextFlag[minSn]=false;
		}
	}
	
	out<<endl;
	out.close();
	for(int i=0;i<fileNum;i++)
	{
		inFile[i].close();
		delete []inFile[i];
	}
	delete []inFile;
	delete []tempDataArray;
	system("pause");	
	return 0;
}
测试文件data.txt数据为:

12 32 5 4 
5 8
9 45 44444 6 8 45 78 9 23 12 45 78 5 2 6 65 68 69 67 62 63 51 52 57 58 59

分批读入后,不同文件数据为:

1.txt  4 5 5 12 32 

2.txt  6 8 9 45 44444 

3.txt  8 9 23 45 78 

4.txt  2 5 12 45 78
5.txt  6 65 67 68 69
6.txt  51 52 57 62 63
7.txt  58 59 

归并后数据为:

2 4 5 5 5 6 6 8 8 9 9 12 12 23 32 45 45 45 51 52 57 58 59 62 63 65 67 68 69 78 78 44444 

方法2:

利用位图进行排序,但是有要求,数据不能重复,总体数据量比较小。因为有多少个数据,就必须定义多少位。一个字节有8位,那么一亿个数据的话接近100M的内存。

这里只对100以内的数进行排序,然后只能用内存中的5位,那么需要20趟才能搞定。也就是说对于6到10的,将踏减去5之后就能用1到5位了,返回的时候加上5输出即可。

代码如下:

#include <iostream>
#include<fstream>
#include<bitset>
using namespace std;
const int MaxScanSize=5;
const int ScanTimes=20;

int main()
{  
	
	ifstream in("data.txt");	
	ofstream out("result.txt");
	bitset<MaxScanSize> BitMap;	//下标从0开始
	for(int i=0;i<ScanTimes;i++)
	{
		BitMap.reset();
		int inData;
		while(!in.eof())
		{	
			in>>inData;
			if(inData>(i*MaxScanSize)&&inData<=(i+1)*MaxScanSize)
				BitMap.set(inData-(i*MaxScanSize)-1,1);
		}
		for(int j=0;j<MaxScanSize;j++)
		{
			if(BitMap[j]==1)
				out<<(i*MaxScanSize)+j+1<<" ";
		}
		in.clear();//必须要清除之后才能重新指向,这是个重大的问题
		in.seekg(0);//指向文件的开头,这里是绝对位置,要想使相对位置可以用seekg(0,ios::beg)
		in>>inData;
	}
	in.close();
	out.close();
	system("pause");	
	return 0;
}
需要注意的几点:

(1)bitset下标是从0开始。

(2)ifstream读数的时候最好用while(!in.eof())

(3)若需要改变流指针的指向,需要先clear,再指向,用seekg这里有绝对和相对指向,同样有seekp为输出流的指向。

(4)适当的用const代替程序中的数字是一个好的习惯,便于维护。

结果如下:

data.txt:

65 68 69 67 62 63 51 52 57 58 59 2 3 8 9 7

result.txt:

2 3 7 8 9 51 52 57 58 59 62 63 67 68 69 


相关的题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值