归并排序实现外排序

外排序,对规模大的数据进行处理。


先通过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;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值