歸併排序(遞迴和非遞迴方法實現)
阿新 • • 發佈:2019-02-16
/* 歸併排序 VS2010 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #define OK 1 #define ERROR 0 #define MAXSIZE 50 typedef struct { int value; }RedType; typedef struct { RedType red[MAXSIZE+1]; int length; }SqList; SqList *CreateSqList() { int i = 0; int j = 0; char buf[4*MAXSIZE] = ""; char *ptr = NULL; SqList *sqlist = (SqList *)malloc(sizeof(SqList)); memset(sqlist, 0, sizeof(SqList)); printf("請輸入待排序資料,以逗號分隔,以分號結束\n" "例:23,12,65,36,35;\n" "input:"); scanf("%s", buf); ptr = buf; sqlist->red[i].value = 0; //red[0]不存值用作哨兵單元 i = 1; while(*ptr != ';') { sqlist->red[i].value = atoi(ptr); i++; ptr = strstr(ptr, ","); if(!ptr) { break; } ptr++; } sqlist->length = (i - 1); return sqlist; } //將有序的src[start...mid]和src[mid+1...end]歸併為有序的TR[start...end] int Merging(RedType src[MAXSIZE+1], RedType *des, int start, int mid, int end) { int i = 0; //作為src[start...mid]的遊標 int j = 0; //作為src[mid+1...end]的遊標 int k = 0; //作為des[start...end]的遊標 i = start; j = mid + 1; k = start; for( ; (i <= mid && j <= end); k++) //將src中記錄由小到大地併入des { if(src[i].value <= src[j].value) { des[k] = src[i]; i++; } else { des[k] = src[j]; j++; } } if(i <= mid) { for( ; i <= mid; i++, k++) { des[k] = src[i]; } } if(j <= end) { for( ; j <= end; j++, k++) { des[k] = src[j]; } } return OK; } //將src[start...end]歸併排序為des[start...end] int MSort(RedType src[], RedType des[], int start, int end) { int mid = 0; RedType tmp[MAXSIZE+1]; if(start == end) { des[start] = src[start]; } else { mid = (start + end) / 2; //將src[start..end]平分為SR[start...mid]和SR[mid+1..end] MSort(src, tmp, start, mid); MSort(src, tmp, (mid + 1), end); Merging(tmp, des, start, mid, end); } return OK; } //對順序表sqlist作歸併排序,採用遞迴的方法 int MergingSort(SqList *sqlist) { MSort(sqlist->red, sqlist->red, 1, sqlist->length); return OK; } //將src[]中相鄰長度為s的子序列兩兩歸併到des[] void MergePass(RedType src[], RedType des[], int s, int length) { int i = 1; int j = 0; while(i <= length - 2 * s + 1) { Merging(src, des, i, i + s - 1, i + 2 * s - 1); //兩兩歸併 i = i + 2 * s; } if(i < length - s + 1) //歸併最後兩個序列 { Merging(src, des, i, i + s - 1, length); } else //若最後只剩下單個子序列 { for(j = i; j <= length; j++) des[j] = src[j]; } } //對順序表sqlist作歸併非遞迴排序 void MergingSort2(SqList *sqlist) { int k = 1; int* tmp = (RedType *)malloc(sqlist->length * sizeof(RedType)); //申請額外空間 while(k < sqlist->length) { MergePass(sqlist->red, tmp, k, sqlist->length); k = 2 * k; //子序列長度加倍 MergePass(tmp, sqlist->red, k, sqlist->length); k = 2 * k; //子序列長度加倍 } } //打印表中資料 int PrintSqList(SqList sqlist) { int i = 0; for(i = 1; i <= sqlist.length; i++) { printf("%d,", sqlist.red[i].value); } printf("\b;\n"); return OK; } int main() { SqList *sqlist = NULL; SqList *testSqList = NULL; sqlist = CreateSqList(); testSqList = (SqList *)malloc(sizeof(SqList)); printf("\n遞迴實現歸併排序:\n"); memcpy(testSqList, sqlist, sizeof(SqList)); PrintSqList(*testSqList); MergingSort(testSqList); PrintSqList(*testSqList); printf("\n非遞迴實現歸併排序:\n"); memcpy(testSqList, sqlist, sizeof(SqList)); PrintSqList(*testSqList); MergingSort2(testSqList); PrintSqList(*testSqList); free(testSqList); free(sqlist); system("pause"); return 0; }