外部排序 简单算法

《数据结构与算法分析——C语言描述》  第七章


外部排序简单算法

虽然是用了归并,涉及到文件,还是挺麻烦的。文件读取之后是不用fseek的话是不能返回的,并且文件我是用文本储存数字,每个数字的字符长度不一样,不能像数组那样随机读取存放,只能一个一个的读。

#include 
#include 
//#include"fatal.h"
#define M 3



typedef int ElementType;

void insertionSort(int *a, int n) {
	int j, p;
	int temp;

	for (p = 1; p < n; p++) {
		temp = a[p];
		for (j = p; j > 0 && temp < a[j - 1]; j--)
			a[j] = a[j - 1];
		a[j] = temp;
	}
}

void swap_my(ElementType *a, ElementType *b) {
	ElementType temp;
	temp = *a;
	*a = *b;
	*b = temp;
}

ElementType median3(ElementType a[], int left, int right) {
	int center = (left + right) / 2;
	if (a[left] > a[center])
		swap_my(&a[left], &a[center]);
	if (a[left] > a[right])
		swap_my(&a[left], &a[right]);
	if (a[center] > a[right])
		swap_my(&a[center], &a[right]);
	swap_my(&a[center], &a[right - 1]);
	return a[right - 1];
}




#define CUTOFF (3)  

void qsort_my(ElementType a[], int left, int right) {
	if (left + CUTOFF <= right) {
		int i, j;
		ElementType pivot;
		pivot = median3(a, left, right);

		i = left;
		j = right - 1;
		while (1) {
			while (a[++i] < pivot) {}

			while (a[--j] > pivot) {}

			if (i < j)
				swap_my(&a[i], &a[j]);
			else
				break;
		}
		swap_my(&a[i], &a[right - 1]);
		qsort_my(a, left, i - 1);
		qsort_my(a, i + 1, right);
	}
	else
		insertionSort(a + left, right - left + 1);
}

void quickSort_my(ElementType a[], int n) {
	qsort_my(a, 0, n - 1);
}

void write(int *a, int n, FILE *out) {
	for (int i = 0; i < n; i++) {
		fprintf(out, "%d ", a[i]);
	}
}

int main() {
	FILE *ta1, *tb1, *tb2;
	int max_memory[M];
	//ta2 = fopen("ta2", "r+");

	//初始化顺序串
	ta1 = fopen("ta1", "r+");
	tb1 = fopen("tb1", "w");
	tb2 = fopen("tb2", "w");
	int n = 0;
	int whereToWrite = 0;//0表示tb1,1表示tb2
	while (!feof(ta1)) {
		int readNum = 0;
		while (readNum < M && fscanf(ta1, "%d", &max_memory[readNum]) != EOF) {
			n++;
			readNum++;
		}
		quickSort_my(max_memory, readNum);
		//交替写到tb1或写到tb2
		if (whereToWrite == 0)
			write(max_memory, readNum, tb1);
		else
			write(max_memory, readNum, tb2);
		whereToWrite = whereToWrite == 0 ? 1 : 0;
	}
	fclose(ta1);
	fclose(tb1);
	fclose(tb2);



	int runLen = M;
	int whereToRead = 1;//0表示ta1,ta2,1表示tb1,tb2
	while (runLen < n) {
		FILE* file[4];
		if (whereToRead == 1) {
			file[0] = fopen("tb1", "r");
			file[1] = fopen("tb2", "r");
			file[2] = fopen("ta1", "w");
			file[3] = fopen("ta2", "w");
		}
		else {
			file[0] = fopen("ta1", "r");
			file[1] = fopen("ta2", "r");
			file[2] = fopen("tb1", "w");
			file[3] = fopen("tb2", "w");
		}
		whereToWrite = 0;//写到哪,要写的两个磁盘中的 第一个磁盘还是第二个磁盘
		int end1 = 0, end2 = 0;//要读的文件的 第一个地盘  第二个磁盘 是否结尾
		while (!end1 || !end2) {
			int i = 0, j = 0;
			int a, b;

			int isHasNumNotWrite1 = 0, isHasNumNotWrite2 = 0;//0表示目前没有缓存数字
			while (i < runLen && j < runLen) {//分别取出两个顺序串
				if (isHasNumNotWrite1 == 0) {
					if (fscanf(file[0], "%d", &a) == 1)//成功读入
					{
						isHasNumNotWrite1 = 1;
					}
					else {
						end1 = 1;//读完了
						break;
					}

				}
				if (isHasNumNotWrite2 == 0) {
					if (fscanf(file[1], "%d", &b) == 1) {
						isHasNumNotWrite2 = 1;
					}
					else {
						end2 = 1;
						break;
					}

				}
				if (a < b) {
					fprintf(file[2 + whereToWrite], "%d ", a);
					i++;
					isHasNumNotWrite1 = 0;
				}
				else {
					fprintf(file[2 + whereToWrite], "%d ", b);
					j++;
					isHasNumNotWrite2 = 0;
				}
			}
			;
			//有可能是成功读入、满了未填满、中途break
			while (end1 == 0 && i < runLen) {
				if (isHasNumNotWrite1 == 0) {
					if (fscanf(file[0], "%d", &a) == 1)
						isHasNumNotWrite1 = 1;
					else {
						end1 = 1;
						break;//必须break,此时没有缓冲数字,也不能读进新的数字,不可以写入
					}

				}
				fprintf(file[2 + whereToWrite], "%d ", a);
				isHasNumNotWrite1 = 0;
				i++;
			}
			while (end2 == 0 && j < runLen) {
				if (isHasNumNotWrite2 == 0) {
					if (fscanf(file[1], "%d", &b) == 1) {
						isHasNumNotWrite2 = 1;
					}
					else {
						end2 = 1;
						break;
					}

				}
				fprintf(file[2 + whereToWrite], "%d ", b);
				isHasNumNotWrite2 = 0;
				j++;
			}
			whereToWrite = whereToWrite == 0 ? 1 : 0;
		}
		for (int i = 0; i < 4; i++)
			fclose(file[i]);
		runLen *= 2;
		whereToRead = (whereToRead == 0) ? 1 : 0;
	}
}


你可能感兴趣的:(外部排序 简单算法)