利用随机函数产生30000个随机整数,利用插入排序、起泡排序、选择排序、快速排序、堆排序、归并排序等排序方法进行排序,并且统计每一种排序上机所花费的时间。
1、折半插入排序:插入排序的基本插入是在一个有序表中进行查找和插入,这个查找可利用折半查找来实现,即为折半插入排序。
2、起泡排序:首先将第一个记录的关键字和第二个记录的关键字进行比较,若为逆序,则将两个记录交换,然后比较第二个记录和第三个记录的关键字。依此类推,直到第N-1和第N个记录的关键字进行过比较为止。上述为第一趟排序,其结果使得关键字的最大纪录被安排到最后一个记录的位置上。然后进行第二趟起泡排序,对前N-1个记录进行同样操作。一共要进行N-1趟起泡排序。
3、快速排序:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,已达到整个序列有序。
4、选择排序:通过N-1次关键字间的比较,第i趟排序是后面N-i+1(i=1,2,3,4,........n-1)个元素中选择一个值最小的元素与该 N-i+1个元素的最前门的那个元素交换位置,即与整个序列的第 i 个元素交换位置。如此下去,直到 i = n - 1,排序结束。简单说就是从N-I+1个记录中选出关键字最小的记录,并和第I(1<=I<=N)个记录交换。
5、堆排序:在堆排序的算法中先建一个大顶堆,既先选得一个关键字作为最大的记录并与序列中最后一个记录交换,然后对序列中前N-1记录进行选择,重新将它调整成一个大顶堆,如此反复直到排序结束。
6、归并排序:归并排序算法采用的是分治算法,即把两个(或两个以上)有序表合并成一个新的有序表,即把待排序的序列分成若干个子序列,每个子序列都是有序的,然后把有序子序列合并成整体有序序列,这个过程也称为2-路归并。
代码如下所示
头文件为:
#define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> #include <stdlib.h> #include<assert.h> #include<malloc.h> #include <time.h>//计时 //#ifndef _CLOCK_T_DEFINED //typedef long clock_t; //#define _CLOCK_T_DEFINED //#endif #define MAX_SIZE 100000 typedef struct SeqList { int *r;//r[0]闲置 int length;//顺序表总长度 }SeqList; enum OP { EXIT, INSERT, BININSERT, BUBBLE, QUICK, SELECT, STACK, MERGE, };
主函数文件为:
#include "SeqList.h" //建立并初始化线性表 void InitSeqList(SeqList* L) { assert(L);//检验指针有效性 L->r = (int *)malloc(MAX_SIZE*sizeof(int));//动态分配空间 if (!L->r) { printf("开辟空间失败!"); return; } L->length = 0; } //产生随机数并显示在界面上 void CreateShow(SeqList* L) { assert(L); int i = 0, n; printf("请输入要排序的元素个数>"); scanf("%d", &n); for (; i <= n; i++) { L->r[i] = rand();//产生随机数 } printf("\n"); printf("随机产生了%d个随机数,它们分别是>\n", n); for (i = 1; i <= n; i++) { printf("%8d ", L->r[i]); } printf("\n"); L->length = n; } //打印出排序后的数据 void PrintSeqList(SeqList* L) { assert(L); printf("数据个数为>%d\n", L->length); printf("排序后的数据为(从小到大进行了排序)>\n"); for (int i = 1; i <= L->length; i++) { printf("%8d ", L->r[i]); } printf("\n"); } //交换两个数 void swap(int* num1, int* num2) { int temp = *num1; *num1 = *num2; *num2 = temp; } //直接插入排序 void InsertSort(SeqList* L) { assert(L); int i, j; if (L->length == 0) { printf("需要排序的数据为空!"); return; } for (i = 2; i <= L->length; i++) { if (L->r[i] < L->r[i - 1])//将L->r[i]插入有序表 { //分析 // 2 3 8 7 9 5 10(选择r[i]=5,i=6) //5 2 3 8 7 9 10 //5 2 3 8 7 9 10 //5 2 3 8 7 9 10(大于5的数都后移) // 2 3 5 8 7 9 10 L->r[0] = L->r[i];//设置监视哨 L->r[i] = L->r[i - 1]; for (j = i - 2; L->r[0] < L->r[j]; j--) { L->r[j + 1] = L->r[j];//大于将要插入数的数后移 } L->r[j + 1] = L->r[0];//插入到正确位置 } } } //折半插入排序 void BinInsert(SeqList* L) { assert(L); int i, j, mid, low, high; if (L->length == 0) { printf("需要排序的数据为空!"); return; } for (i = 2; i <= L->length; i++) {//折半查找 //分析 // 2 3 8 7 9 5 10(选择r[i]=5,i=6) //5 2 3 8 7 9 10 //5 2 3 8 7 9 10(折半查找结束后,low为2,high为3) //5 2 3 8 7 9 10(大于5的数8、7、9都后移) // 2 3 5 8 7 9 10 L->r[0] = L->r[i];//将L->r[0]暂存在L->r[0] low = 1; high = i - 1; while (low <= high) { mid = low - (low - high) / 2; if (L->r[0] < L->r[mid]) { high = mid - 1;//插入到低半部分 } else { low = mid + 1;//插入到高半部分 } } for (j = i - 1; j >= high + 1; j--) { L->r[j + 1] = L->r[j]; } L->r[high + 1] = L->r[0];//将要插入的数据插入 } } //冒泡排序 void BubbleSort(SeqList* L) { assert(L); int i, j, flag;//冒泡排序的优化就是定义一个标志位flag,接近有序时停止冒泡 if (L->length == 0) { printf("需要排序的数据为空!"); return; } for (j = 1; j <= L->length - 1; j++)//总共比较L->length-1趟 { for (i = 1; i <= L->length - j; i++)//每一趟冒泡出一个最大数 { flag = 0; if (L->r[i] > L->r[i + 1]) {//交换两个数 swap(&L->r[i], &L->r[i + 1]); flag = 1; } } if (flag == 0) break; } } //快速排序(分治递归) void QuickSort(SeqList* L, int low, int high) { assert(L); int mid; int left = low; int right = high; if (L->length == 0) { printf("要排序的数据为空!"); return; } mid = L->r[low - (low - high) / 2];//选取的参照中间值 do { while (L->r[left] < mid && left < high)//从左到右找比mid大的元素 left++; while (L->r[right] > mid && right > low)//从右到左找比mid小的元素 right--; if (left <= right)//若找到且满足条件,则交换 { swap(&L->r[left++], &L->r[right--]); } } while (left <= right); if (left < high) QuickSort(L, left, high);//运用递归 if (low < right) QuickSort(L, low, right); } //选择排序 void SelectSort(SeqList* L) { assert(L); int i, j, min, max; if (L->length == 0) { printf("需要排序的数据为空!"); return; } for (i = 1; i <= L->length - 1; i++)//排序的趟数L->length-1 { min = i; max = L->length - 1; for (j = i; j <= max; j++) {//比较第i个元素和其后的元素找到最小的和最大的 if (L->r[j] < L->r[min]) { swap(&L->r[min], &L->r[j]);//交换两个数,每一趟将最小数放在前面 } if (L->r[j] > L->r[max]) { swap(&L->r[max], &L->r[j]);//交换两个数,每一趟将最大数放在后面 } } } } //堆排序 void HeapAdjust(SeqList* L, int s, int m)//调整L->r[s]的关键字,使L->r[s-m]成大顶堆 { assert(L); int i; L->r[0] = L->r[s]; for (i = 2 * s; i <= m; i *= 2)//沿数据较大的孩子结点向下筛选 { if (i < m && (L->r[i] < L->r[i + 1]))//i为数据较大的记录下标 i++; if (L->r[0] >= L->r[i]) //L->r[0]插入在s位置上 break; L->r[s] = L->r[i]; s = i; } L->r[s] = L->r[0]; //插入新数据 } void HeapSort(SeqList* L) { assert(L); int i; if (L->length == 0) { printf("没有数据!"); return; } for (i = L->length / 2; i > 0; i--) HeapAdjust(L, i, L->length); for (i = L->length; i > 1; i--) {//将堆顶记录和当前未经排序的子序列L->r[1..i]中最后一个记录互换 swap(&L->r[1], &L->r[i]); HeapAdjust(L, 1, i - 1); //将L->r[1..i-1]重新调整为大顶堆 } } //归并排序函数的具体实现 void MergeArray(SeqList* L, int low, int mid, int high) { assert(L); int i, j, k, len1, len2; int *front, *back; len1 = mid - low + 1;//前一部分的长度 len2 = high - mid;//后一部分的长度 front = (int*)malloc(len1*sizeof(int));//申请两个空间存放排好的数组 back = (int*)malloc(len2*sizeof(int)); //将数组转入两个新空间中 for (i = 0; i < len1; i++) front[i] = L->r[low + i]; for (j = 0; j < len2; j++) back[j] = L->r[mid + j + 1]; //合并元素 i = 0; j = 0; k = low; while (i < len1&&j < len2) {//L->r[]中依次放入两个数组中较小数 if (front[i] < back[j]) L->r[k++] = front[i++]; else L->r[k++] = back[j++]; } //将剩余元素合并 while (i < len1) L->r[k++] = front[i++]; while (j < len2) L->r[k++] = back[j++]; } //归并排序函数的具体实现 void MergeSort(SeqList* L, int low, int high) { assert(L); int middle; if (L->length == 0) { printf("要排序的数据为空!"); return; } if (low<high) { middle = low - (low - high) / 2; MergeSort(L, low, middle);//将前面一部分用递归的方法排序 MergeSort(L, middle + 1, high); //将后面一部分用递归的方法排序 MergeArray(L, low, middle, high);//再将二个有序数列合并 } } void menu() { printf("\n\t*****************算法排序比较系统****************"); printf("\n\t-------------------------------------------------\n"); printf("\t*********** 1、直接插入排序 ***********\n"); printf("\t*********** 2、折半插入排序 ***********\n"); printf("\t*********** 3、起泡排序 ***********\n"); printf("\t*********** 4、快速排序 ***********\n"); printf("\t*********** 5、选择排序 ***********\n"); printf("\t*********** 6、堆排序 ***********\n"); printf("\t*********** 7、归并排序 ***********\n"); printf("\t*********** 0、退出系统 ***********\n"); } int main() { SeqList L; srand((unsigned int)time(NULL)); InitSeqList(&L);//初始化L int n = 1; clock_t start, end; //clock_t用于计时开始时间和结束时间 while (n) { menu(); printf("请选择你要排序的方式(数字1~7)或退出系统(数字0)>"); scanf("%d", &n); switch (n) { case INSERT: start = clock(); CreateShow(&L); InsertSort(&L); end = clock(); PrintSeqList(&L); printf("插入排序时间是:%f毫秒\n", (float)(end - start)); break; case BININSERT: start = clock(); CreateShow(&L); BinInsert(&L); end = clock(); PrintSeqList(&L); printf("插入排序时间是:%f毫秒\n", (float)(end - start)); break; case BUBBLE: start = clock(); CreateShow(&L); BubbleSort(&L); end = clock(); PrintSeqList(&L); printf("插入排序时间是:%f毫秒\n", (float)(end - start)); break; case QUICK: start = clock(); CreateShow(&L); QuickSort(&L, 1, L.length); end = clock(); PrintSeqList(&L); printf("插入排序时间是:%f毫秒\n", (float)(end - start)); break; case SELECT: start = clock(); CreateShow(&L); SelectSort(&L); end = clock(); PrintSeqList(&L); printf("插入排序时间是:%f毫秒\n", (float)(end - start)); break; case STACK: start = clock(); CreateShow(&L); HeapSort(&L); end = clock(); PrintSeqList(&L); printf("插入排序时间是:%f毫秒\n", (float)(end - start)); break; case MERGE: start = clock(); CreateShow(&L); MergeSort(&L, 1, L.length); end = clock(); PrintSeqList(&L); printf("插入排序时间是:%f毫秒\n", (float)(end - start)); break; case EXIT:printf("感谢使用本系统,欢迎下次使用!"); break; default:printf("您输入的序号错误!请重新选择>\n"); break; } } system("pause"); return 0; }
各种排序算法的最差时间,时间复杂度及稳定性比较
排序算法 | 最差时间 | 时间复杂度 | 是否稳定 |
插入排序 | O(n2) | O(n2) | 稳定 |
冒泡排序 | O(n2) | O(n2) | 稳定 |
快速排序 | O(n2) | O(n*log2n) | 不稳定 |
选择排序 | O(n2) | O(n2) | 稳定 |
堆排序 | O(n*log2n) | O(n*log2n) | 不稳定 |
归并排序 | O(n*log2n) | O(n*log2n) | 稳定 |