外排序,对规模大的数据进行处理。
先通过data_make制造随机数到文件名为path的文件中去。
bool data_make(char *path, int num)
{
FILE * fw = fopen(path, "wb");
if(fw == NULL)
{
return false;
}
srand(100);
for(int i=0; i<num; i++)
{
int x = rand();
fwrite(&x, sizeof(int), 1, fw);
}
fclose(fw);
return true;
}
然后进行文件文件中的合并,其基本思想与归并排序一致,只是将在内存中的排序转换到文件中而已。
bool mager(char *path, char *tmp_path, int gap)
{
FILE *fr = fopen(path, "rb");
int *dat1 = (int *)malloc(sizeof(int)*gap);
int *dat2 = (int *)malloc(sizeof(int)*gap);
int *dat3 = (int *)malloc(sizeof(int)*gap);
FILE *fw = fopen(tmp_path , "wb");
if (dat1 == NULL || dat2 == NULL || dat3 == NULL || fr == NULL || fw == NULL)
{
return false;
}
int e1 = 0; //与文件中的游标同步运动
int r1 = e1+gap-1;
int e2 = r1+1;
int r2 = e2+gap-1 < MAX_SIZE-1 ? e2+gap-1 : MAX_SIZE-1;
int k = 0;
int i = gap;
int j = gap; // I,j,k是开辟的对空间中的数组下标
while(e2 < MAX_SIZE) //1与2中有都数据,如果只有1中有数据的话就直接将其后面的数据写入到文件中去
{
if (i == gap) //一旦到了临界值,就去读文件中的数据
{
fread(dat1, sizeof(int), gap, fr);
i = 0;
}
if (j == gap)
{
fread(dat2, sizeof(int), gap, fr);
j = 0;
}
while(e1 <= r1 && e2 <= r2) //归并段1有数据,2有数据,进行比较然后将小的先放下去
{
if (*(dat1+i) < *(dat2+j))
{
*(dat3+k) = *(dat1+i);
k++;
e1++;
i++;
}
else
{
*(dat3+k) = *(dat2+j);
k++;
e2++;
j++;
}
if(k == gap) //第三存储中数据满后写入文件
{
fwrite(dat3, sizeof(int), gap, fw);
k = 0;
}
}
fwrite(dat3, sizeof(int), k, fw); //将第三存储中的数据写入到文件
k = 0;
//1中有数据,2中没有 1中有数据,2中有部分数据 //排序中如果有一数组中已经没有数了,那就将另一组有数据的数给落下来
int tmp = 0;
while (e1 <= r1)
{
tmp = dat1[i];
fwrite(&tmp, sizeof(int), 1, fw);
i++;
e1++;
}
while (e2 <= r2)
{
tmp = dat2[j];
fwrite(&tmp, sizeof(int), 1, fw);
j++;
e2++;
}
e1 = r2+1;
r1 = e1+gap-1;
e2 = r1+1;
r2 = e2+gap-1 < MAX_SIZE-1 ? e2+gap-1 : MAX_SIZE-1;
}
//大循环结束
int ch = 0;
while (e1 <= MAX_SIZE-1)//文件中
{
fseek(fr, e1*sizeof(int), SEEK_SET);
fread(&ch, sizeof(int), 1, fr);
fwrite(&ch, sizeof(int), 1, fw); //将dat1中剩下的数字读到文件中
e1++;
}
free(dat1);
free(dat2);
free(dat3);
fclose(fr);
fclose(fw);
return true;
}
先进行一一归并,二二归并,四四归并...直到i超过数据的一半后,整个数据全部的有序
bool file_meger_sort(char *path)
{
if (path == NULL)
{
return false;
}
char tmp_path[125] = "E:\\tmp.txt";
char temp[128];
for (int i=1; i< MAX_SIZE; i=i*2)
{
mager(path, tmp_path,i);
strcpy(temp, path); //也可在mager()中通过remove()函数和rename()函数进行文件的删除与文件重命名</span>
strcpy(path,tmp_path);
strcpy(tmp_path,temp);
}
remove(tmp_path);
return true;
}
//打印文本中的数据
bool data_read(char *path)
{
FILE *fr = fopen(path, "rb");
if (fr == NULL)
{
return false;
}
int *data = (int *)malloc(sizeof(int) * MAX_SIZE);
assert(data != NULL);
int num = 0;
while ((num = fread(data,sizeof(int), MAX_SIZE, fr)) != 0)
{
int i = 0;
while (i<num)
{
printf("%5d ", *(data+i));
i++;
if (i%5 == 0)
{
printf("\n");
}
}
}
free(data);
return true;
}