外部排序 替换选择

来源:互联网 发布:淘宝网官网登陆 编辑:程序博客网 时间:2024/05/16 11:41

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


#include <stdio.h>#include<queue>#include"fatal.h"#define M 3//最大的内存#define N 33//要排序的数字量,1—Ntypedef int ElementType;char name[200];//生成的名字std::queue<int> notHandleFile;std::queue<int> nullFile;char* fileName(char *buf, int i) {strcpy(buf, "T");char num[5];strcat(buf, _itoa(i + 1, num, 10));return buf;}int RandInt(int i, int j) {int temp;temp = (int)(i + (1.0*rand() / RAND_MAX)*(j - i));return temp;}void getRandomInt(int *A, int n) {for (int i = 0; i < n; i++) {A[i] = i + 1;}for (int i = 1; i < n; i++) {//std::swap(A[i], A[RandInt(0, i)]);      int randAdrr = RandInt(0, i);int t = A[i];A[i] = A[randAdrr];A[randAdrr] = t;}}void writeRandIntToFile() {int a[N];getRandomInt(a, N);FILE *fp = fopen("ta1", "w");for (int &i : a)fprintf(fp, "%d ", i);fclose(fp);}#define leftChild(i) (2*(i)+1)  //下标从0开始void percDown(int *a, int i, int n) {int child = leftChild(i);int temp;for (temp = a[i]; leftChild(i) < n; i = child) {child = leftChild(i);if (child != n - 1 && a[child] > a[child + 1])child++;if (temp > a[child])a[i] = a[child];elsebreak;}a[i] = temp;}void buildHeap(int *arr, int n) {for (int i = (n - 1 - 1) / 2; i >= 0; i--) {percDown(arr, i, n);}}void insertHeap(int *arr, int &n) {int i;int X = arr[n];n++;for (i = n - 1; i > 0 && arr[(i - 1) / 2] > X; i = (i - 1) / 2)//下表为0的时候就是根节点,不用上滤了arr[i] = arr[(i - 1) / 2];arr[i] = X;}int deleteMin(int *arr, int &n) {//n为数量int i, child;ElementType minElement, lastElement;minElement = arr[0];lastElement = arr[n - 1];//删除右下的元素  n--;for (i = 0; i <n; i = child) {child = leftChild(i);if (child >= n)//这个用于在最底层的时候,获得的儿子是越界的,此时i是上一次迭代的child,child两儿子中的最小值  break;if (child != n - 1 && arr[child] > arr[child + 1]) {//不一定有两个儿子  child++;}if (lastElement > arr[child])arr[i] = arr[child];elsebreak;}arr[i] = lastElement;return minElement;}void initRun(char *inputFileName) {FILE* readFp = fopen(inputFileName, "r");if (readFp == NULL)Error("OPEN FILE FAILED");int fileNum = 0;//文件数量int arr[M];//二叉堆的数组int size = 0;//有效数字个数int deadSpace = M - 1;//死区下标while (size < M && fscanf(readFp, "%d", &arr[size]) == 1) {//读入数字初始化堆size++;}do {FILE *writeFile = fopen(fileName(name, fileNum), "w");buildHeap(arr, size);while (size != 0) {//堆不是空int min = deleteMin(arr, size);fprintf(writeFile, "%d ", min);if (fscanf(readFp, "%d", &arr[deadSpace]) == 1) {//输出了一个数,再读取一个数if (arr[deadSpace]>min) {//放到堆中insertHeap(arr, size);//此时size和deadSize是相同的}else {//放到死区中deadSpace--;}}}fclose(writeFile);notHandleFile.push(fileNum);fileNum++;//下一个串size = M - 1 - deadSpace;//求死区中元素的数量deadSpace = M - 1;//初始化死区下标if (size > 0 && size<M) {//当死区元素没填满的时候从右边移动到左边for (int i = 0; i < size; i++) {arr[i] = arr[i + M - size];}}} while (!feof(readFp));nullFile.push(fileNum);}void mergeRun(int file1, int file2, int writefile) {FILE *readFp1 = fopen(fileName(name, file1),"r");FILE *readFp2 = fopen(fileName(name, file2), "r");FILE *writeFp = fopen(fileName(name, writefile), "w");int a, b;int hasNum1 = 0, hasNum2 = 0;while ((hasNum1==1||fscanf(readFp1, "%d", &a)==1)&& (hasNum2 == 1 || fscanf(readFp2, "%d", &b) == 1)) {hasNum1 = 1;hasNum2 = 1;if (a < b) {fprintf(writeFp, "%d ", a);hasNum1 = 0;}else {fprintf(writeFp, "%d ", b);hasNum2 = 0;}}while ((hasNum1 == 1 || fscanf(readFp1, "%d", &a) == 1)) {fprintf(writeFp, "%d ", a);hasNum1 = 0;}while (hasNum2 == 1 || fscanf(readFp2, "%d", &b) == 1) {fprintf(writeFp, "%d ", b);hasNum2 = 0;}fclose(readFp1);fclose(readFp2);fclose(writeFp);}int main() {writeRandIntToFile();char inputFileName[20] = "ta1";//要排序的文件//scanf("%s", inputFileName);initRun(inputFileName);//初始化顺序串int cnt = 0;while (notHandleFile.size() > 1) {int file1 = notHandleFile.front();notHandleFile.pop();int file2 = notHandleFile.front();notHandleFile.pop();int writeFile = nullFile.front();nullFile.pop();mergeRun(file1, file2, writeFile);nullFile.push(file1);nullFile.push(file2);notHandleFile.push(writeFile);}}


0 0