1)问题描述和分析
我们计算机的内存是有限的,当我们需要处理的数据超出我们的内存的时候就需要我们借助磁盘来进行排序,这种排序被称为外部排序,外部排序通常由归并排序实现.
2)设计与实现
我们将所需要处理的数据放入存入txt文件,假设要处理50000个数据,将这些数据分为100个文件,每个文件500个数据,利用内部排序使这些文件中的数据有序,之后利用队列对这些数据进行归并排序.
3)测试例子与结果分析
排序前的部分数据为:
利用随机数生成50000个数据
排序后的部分数据为:
4)源代码
#include<stdio.h>
#include<stdlib.h>
#define ROOT "C:\\Users\\HP\\Desktop\\新建文件夹" //根目录
#define N 100 //文件总个数
typedef struct{//创建一个双向循环队列保存结点
FILE *f;
struct Node *next;
struct Node *pre;
}Node;
Node *initQueue(){
Node *head=(Node*)malloc(sizeof(Node));
head->f=NULL;
head->next=NULL;
head->pre=NULL;
Node *p=head;//保存尾结点
int i;
for(i=0;i<N;i++){//循环创造结点
Node *temp=(Node*)malloc(sizeof(Node));
char name[99];
sprintf(name,"%s\\%d.txt",ROOT,i);//设置文件名称
temp->f=fopen(name,"a+");
temp->next=p;
head->next=temp;
temp->pre=head;
p->pre=temp;
head=temp;
}
return p;//返回头结点
}
FILE * merge(FILE *r,FILE *y,int n)//传入要排序的两个文件指针 //进行一次归并排序
{
char name[99];
sprintf(name,"%s\\file%d.txt",ROOT,n);//设置文件夹名字
FILE *p=fopen(name,"a+");
int i,j;
int tempr,tempy;
tempr=fscanf(r,"%d",&i);//文件结尾标志
tempy=fscanf(y,"%d",&j);
while(tempr>0&&tempy>0){//判断是否到文件结尾
if(i<j){
fprintf(p,"%d ",i);//将i放入文件
tempr=fscanf(r,"%d",&i);
}
else{
fprintf(p,"%d ",j);//将j放入文件
tempy=fscanf(y,"%d",&j);
}
}
if(tempr>0){
fprintf(p,"%d ",i);
while(fscanf(r,"%d",&i)>0)fprintf(p,"%d ",i);
}//将剩下的数字传入文件
else if(tempy>0){
fprintf(p,"%d ",j);
while(fscanf(y,"%d",&j)>0)fprintf(p,"%d ",j);
}
rewind(p);//重新指向函数头
return p;
}
FILE * mergesort(){
Node *head=initQueue();//初始化队列
Node *p=head->next;//p是第一个节点
int flag=0;//记录文件数量
while(p->next!=head){//当队列中仅有一个结点时退出循环
Node* temp=(Node*)malloc(sizeof(Node));
Node *t=p->next;
temp->f=merge(p->f,t->f,flag);
flag++;
temp->next=head;//排序后的结点加在队列后
temp->pre=head->pre;
Node *prep=temp->pre;
prep->next=temp;
head->pre=temp;
prep=p->next;
head->next=prep->next;//将排序前的两个结点删除
p=head->next;//更新p
p->pre=head;
}
return p->f;
}
void CreatFile(FILE *f){//将一个大文件分成若干个小文件
int i;
int num;
for(i=0;i<N;i++)
{
int j;
int flag=1;
FILE *temp;
char name[99];
sprintf(name,"%s\\%d.txt",ROOT,i);//设置文件名称
temp=fopen(name,"a+");
int arr[500];
for(j=0;j<500;j++){
if(fscanf(f,"%d",&num)>0)
arr[j]=num;
//fprintf(temp,"%d ",num);//每500个一个文件
else {
flag=0;
break;
}
}
int fi,fj;
for(fi=0;fi<499;fi++){
for(fj=0;fj<499-fi;fj++){
if(arr[fj]>arr[fj+1]){
int temp=arr[fj];
arr[fj]=arr[fj+1];
arr[fj+1]=temp;
}
}
}
if(flag==0)break;
for(fj=0;fj<500;fj++){
fprintf(temp,"%d ",arr[fj]);
}
fclose(temp);
}
}
FILE* Textdata(){
FILE *f=fopen("C:\\Users\\HP\\Desktop\\新建文件夹\\text.txt","a+");
int i;
for(i=0;i<50000;i++)fprintf(f,"%d ",rand());
rewind(f);
return f;
}
int main(){
FILE *p=Textdata();
CreatFile(p);
p=mergesort();
return 0;
}