这是个外部排序的算法课作业
首先GenerateData()函数生成一个包含10*MAXN个随机int数据的文件data.txt。
然后Part()函数将其分为10个小文件。
接下来FileSort()函数分别对每一个小文件进行排序,并将排序以后的数据存入该小文件。
最后Merge()函数将各小文件中的数据归并到大文件finalsort.txt中。
几点说明:
1.本程序会自动生成数据文件,无需附属数据文件。
2.由于rand()函数只能生成32767以下的随机数,不能满足要求,我从网上找了一个产生随机数的程序。
3.MAXN是事先定义好的内存最大容量,我这里采用的是100万。
4.小文件排序采用的是快速排序。
5.Merge()的具体方法是每次从排序好的10小文件中取出最前面的数,放入优先队列中,从优先队列中拿出最小的放入finalsort.txt,并从该小文件中继续取出最前面的数放入优先队列中,如此反复直到最终优先队列为空。
6.本程序在i7-4790 CPU 3.60GHz 8G内存 64位台式机上运行时间为20.122秒。
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
#define MAXN 1000000
FILE *f[15];
char name[15][15];
int a[MAXN+5];
struct num
{
int id;
int n;
bool operator< (const num &num1) const
{
return n>num1.n;
}
};
priority_queue<num> que;
/*************************** 以下为产生随机数的程序 ****************************************/
#define NN 624
#define MM 397
#define MATRIX_A 0x9908b0df /* constant vector a */
#define UPPER_MASK 0x80000000 /* most significant w-r bits */
#define LOWER_MASK 0x7fffffff /* least significant r bits */
#define TEMPERING_MASK_B 0x9d2c5680
#define TEMPERING_MASK_C 0xefc60000
#define TEMPERING_SHIFT_U(y) (y >> 11)
#define TEMPERING_SHIFT_S(y) (y << 7)
#define TEMPERING_SHIFT_T(y) (y << 15)
#define TEMPERING_SHIFT_L(y) (y >> 18)
static unsigned long mt[NN]; /* the array for the state vector */
static int mti=NN+1; /* mti==NN+1 means mt[NN] is not initialized */
void sgenrand(unsigned long seed)
{
int i;
for (i=0;i<NN;i++)
{
mt[i] = seed & 0xffff0000;
seed = 69069 * seed + 1;
mt[i] |= (seed & 0xffff0000) >> 16;
seed = 69069 * seed + 1;
}
mti = NN;
}
void lsgenrand(unsigned long seed_array[])
{
int i;
for (i=0;i<NN;i++)
mt[i] = seed_array[i];
mti=NN;
}
double genrand()
{
unsigned long y;
static unsigned long mag01[2]={0x0, MATRIX_A};
if (mti >= NN)
{
int kk;
if (mti == NN+1) sgenrand(4357);
for (kk=0;kk<NN-MM;kk++) {
y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
mt[kk] = mt[kk+MM] ^ (y >> 1) ^ mag01[y & 0x1];
}
for (;kk<NN-1;kk++) {
y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
mt[kk] = mt[kk+(MM-NN)] ^ (y >> 1) ^ mag01[y & 0x1];
}
y = (mt[NN-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
mt[NN-1] = mt[MM-1] ^ (y >> 1) ^ mag01[y & 0x1];
mti = 0;
}
y = mt[mti++]; y ^= TEMPERING_SHIFT_U(y); y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B;
y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C; y ^= TEMPERING_SHIFT_L(y);
return y;
}
double randf(){ return ( (double)genrand() * 2.3283064370807974e-10 ); }
long long randi(unsigned long LIM){ return((unsigned long)genrand() % LIM); }
/********************** 以上为产生随机数的程序 ************************************/
//int RandInt(int maxvalue)
//{
// int randvalue;
// if(maxvalue<=0) return 0;
// randvalue = (int)randi(maxvalue); //产生一个0到maxvalue-1的整数
// return randvalue;
//}
void GenerateData()
{
FILE *p;
p=fopen("data.txt","w");
for(int i=0; i<MAXN*10; i++)
fprintf(p,"%d\n",randi(65535));
fclose(p);
}
void Openfile()
{
for(int i=0; i<10; i++)
{
for(int j=0; j<14; j++) name[i][j]='\0';
strcpy(name[i],"file");
name[i][4]=i+'0';
strcat(name[i],".txt");
}
// for (int i = 0; i < 10; i++)
// {
// fprintf(f[i], "%d ", 34);
// }
}
void Sort(int a[], int s, int t)
{
if(s>=t) return ;
int p=a[s],i=s,j=t;
while(i<j)
{
//cout<<j<<endl;
while(i<j&&a[j]>=p) j--;
if(i<j) a[i++]=a[j];
while(i<j&&a[i]<=p) i++;
if(i<j) a[j--]=a[i];
}
a[i]=p;
//cout<<s<<" "<<j<<" "<<t<<endl;
Sort(a,s,i-1);
Sort(a,i+1,t);
}
void FileSort(int i)
{
int n=MAXN-1;
f[i] = fopen(name[i], "r");
//freopen(name[i],"r",stdin);
//cout<<name[i]<<endl;
for(int j=0; j<=n; j++)
{
fscanf(f[i],"%d",&a[j]);
//cout<<a[j]<<endl;
}
//cout<<a[n-100]<<endl;
fclose(f[i]);
f[i] = fopen(name[i], "w");
Sort(a,0,n);
//cout<<a[n]<<endl;
for(int j=0; j<=n; j++)
{
//cout<<a[j]<<endl;
fprintf(f[i],"%d\n",a[j]);
}
fclose(f[i]);
}
void Part()
{
int x;
FILE *p;
p=fopen("data.txt","r");
for(int i=0; i<10; i++)
f[i] = fopen(name[i], "w");
for (int i = 0; i < 10; i++)
{
for(int j=0; j<MAXN; j++)
{
fscanf(p,"%d",&x);
fprintf(f[i], "%d\n", x);
}
}
fclose(p);
for(int i=0; i<10; i++)
fclose(f[i]);
}
void Merge()
{
int x;
FILE *p;
num a;
p=fopen("finalsort.txt","w");
for(int i=0; i<10; i++)
f[i] = fopen(name[i], "r");
for (int i = 0; i < 10; i++)
{
fscanf(f[i],"%d",&x);
a.id=i;
a.n=x;
que.push(a);
}
while(!que.empty())
{
a=que.top();
que.pop();
fprintf(p, "%d\n", a.n);
int i=a.id;
if(!feof(f[i]))
{
fscanf(f[i],"%d",&x);
a.n=x;
que.push(a);
}
}
fclose(p);
for(int i=0; i<10; i++)
fclose(f[i]);
}
int main()
{
srand((unsigned)time(0));
Openfile();
GenerateData();
Part();
for(int i=0; i<10; i++)
FileSort(i);
Merge();
return 0;
}