数据结构课设——排序综合(C语言)
文章目录
题目
利用随机函数产生N个随机整数(20000以上),对这些数进行多种方法进行排序。
要求:
- 至少采用四种方法实现上述问题求解(提示,可采用的方法有插入排序、希尔排序、冒泡排序、快速排序、选择排序、堆排序、归并排序)。并把排序后的结果保存在不同的文件中。
- 统计每一种排序方法的性能(以上机运行程序所花费的时间为准进行对比,),找出其中两种较快的方法。
本程序中用到了6种排序方法。
随机数的生成
srand((unsigned)time(NULL));
srand
用来初始化随机种子,会提供一个种子,这个种子会对应一个随机数。
为了防止随机数每次重复,这里使用系统时间来作为随机种子。
1.插入排序
步骤
- 从第一个元素开始,该元素可以认为已经被排序
- 取下一个元素
temp
,从已排序的元素序列从后往前遍历 - 如果该元素大于
temp
,则将该元素移到下一位 - 重复步骤3,直到找到已排序元素中小于等于
temp
的元素 temp
插入到元素的后面,如果已排序的元素都大于temp
,则将temp
插入到下标为0的位置- 重复步骤2~5
动图演示如下:
void insertSort() { for (int i = 1; i < CAPACITY; i++) { int temp = array[i]; int j = i - 1; while (j >= 0) { //说明前面已经有序了 if (array[j] <= temp) { break; } //移动j的值到j+1 array[j + 1] = array[j]; j--; } array[j + 1] = temp; } }
时间复杂度:最坏情况:O(),最好情况 O(N)
空间复杂度:O(1)
稳定性:稳定
2.希尔排序
希尔排序又称缩小增量法
步骤
- 先定义一下分组个数gap
- 把整个数组分成gap个组,每个组里有
CAPACITY/gap
个元素 - 把每个小组分别用插入方式排序
- 逐渐缩小这个gap,直到gap=1时,全部排序完成
void shellSort() { int gap = CAPACITY / 2; while (gap > 0) { shell( gap); gap /= 2; } } //核心代码 void shell( int gap) { for (int i = gap; i < CAPACITY; i++) { int temp = array[i]; int j = i - gap; while (j >= 0) { if (array[j] <= temp) { break; } array[j + gap] = array[j]; j -= gap; } array[j + gap] = temp; } }
时间复杂度:O(
空间复杂度:O(1)
稳定性:不稳定
3.冒泡排序
左边大于右边交换一趟排下来最大的在右边
void bubbleSort() { for (int i = 0; i < CAPACITY - 1; i++) { int set = 0; for (int j = 0; j < CAPACITY - 1 - i; j++) { if (array[j] > array[j + 1]) { swap(j, j + 1); set = 1; } } if (set==0) { break; } } } void swap(int left, int right) { int temp = array[left]; array[left] = array[right]; array[right] = temp; }
4.快速排序
挖坑法找基准
left
下标的值当做默认的基准值,这时left
的位置就空出来了right
向左移动,找到比基准值小的值,放到left
的位置left
向右移动,找到比基准值大的值,放到right
的位置- 当
left
与right
相遇时,把之前记录的基准值放在相遇的下标 - 返回相遇点下标,这就是基准的下标
//快速排序 void quickSort() { const int N = 1e2; start = clock(); quickSortProcess(0, CAPACITY - 1); end = clock(); printf("time: %f s\n", ((double)(end - start)) / CLOCKS_PER_SEC / N); } //核心代码 void quickSortProcess(int left, int right) { if (left>=right) { return; } //找基准 int pivot= partitionHole(left, right); quickSortProcess(left, pivot); quickSortProcess( pivot+1,right); } int partitionHole(int left, int right) { int pivotValue = array[left]; while (left < right) { while (right > left && array[right] >= pivotValue) { right--; } array[left] = array[right]; while (left < right && array[left] <= pivotValue) { left++; } array[right] = array[left]; } array[left] = pivotValue; return left; }
5.选择排序
步骤
定义数组边界,left=0,right=CAPACITY-1
定义i用来遍历
定义最小值下标minIndex=left,maxIndex=left
在i遍历的过程中,找到比最小值小的元素更新minIndex,找到比最大值大的元素更新maxIndex
一轮遍历完成后,left与minIndex交换,right与maxIndex交换
循环终止条件是left<rigth
//选择排序 void selectSort() { int left = 0; int right = CAPACITY - 1; while (left < right) { int minIndex = left; int maxIndex = left; //找最大值和最小值 for (int i = left + 1; i <= right; i++) { if (array[i] < array[minIndex]) { minIndex = i; } if (array[i] > array[maxIndex]) { maxIndex = i; } } if (left != minIndex) { swap(left, minIndex); } if (left == maxIndex) { minIndex = maxIndex; } if (right != maxIndex) { swap(right, maxIndex); } left++; right--; } }
6.归并排序
步骤
- 把大数组分解成若干个小数组
- 把小数组做归并操作,并在归并的过程中完成排序
- 在归并的过程中,需要用到一个临时数组来存储排序好的数据,那么这个数组的容量为
right-left+1
- 确定每个小数组的开始与结束下标
- 合并两个数组,合并的方法可以参考合并有序数组的过程
- 两个数组都不为空的情况下,比当前位置元素的大小,小的那一个直接加入到临时数组里
- 如果两个数组的元素个数不一样多,那么就要处理有剩余元素的数组,直接把剩余元素追加到临时数组里
- 把临时数组中排序好的元素,覆盖到原数组对应的下标
//归并排序 void mergeSort() { mergeSortProcessor( 0, CAPACITY - 1); } void mergeSortProcessor(int left, int right) { //1、终止条件 if (left >= right) { return; } //2、找中间下标 int mid = (left + right) / 2; //3、分解左右区段 mergeSortProcessor( left, mid); mergeSortProcessor( mid + 1, right); //4、合并 marge( left, mid, right); } void marge(int left, int mid, int right) { //1、创建临时数组 //int n = (right - left + 1); int *temp=(int*)malloc((right - left + 1)*sizeof(int)); int index = 0; //2、确定每个小数组的下标 int start1 = left; int end1 = mid; int start2 = mid + 1; int end2 = right; //3、合并 while (start1 <= end1 && start2 <= end2) { if (array[start1] < array[start2]) { temp[index++] = array[start1++]; } else { temp[index++] = array[start2++]; } } //剩余元素添加到temp中 while (start1 <= end1) { temp[index++] = array[start1++]; } while (start2 <= end2) { temp[index++] = array[start2++]; } //4、temp写到原数组中 for (int i = 0; i < index; i++) { array[i + left] = temp[i]; } free(temp); temp = NULL; }
完整代码
sort.h
#pragma once #include<stdio.h> #include<stdlib.h> #include<string.h> #include<time.h> #define CAPACITY 20000 int array[CAPACITY]; clock_t start, end; void initArray(); void save(char* name1); void dispaly(); void swap(int i, int minIndex); //插入排序 void insertSort(); //希尔排序 void shellSort(); void shell(int gap); //冒泡排序 void bubbleSort(); //快速排序 void quickSort(); void quickSortProcess(int left, int right); int partitionHole(int left, int right); //选择排序 void selectSort(); //归并排序 void mergeSort(); void mergeSortProcessor(int left, int right); void marge(int left, int mid, int right);
sort.c
#include"sort.h" void initArray() { srand((unsigned)time(NULL)); for (int i = 0; i < CAPACITY; i++) { array[i] = rand(); } } void save(char* name1) { FILE* fp; char* name2 = ".txt"; char* name = (char*)malloc(strlen(name1) + strlen(name2)); strcpy(name, name1); strcat(name, name2); fp = fopen(name, "w"); int count = 0; for (int i = 0; i < CAPACITY; i++) { fprintf(fp, "%6d", array[i]); count++; if (count%100==0) { fprintf(fp, "\n"); } } fclose(fp); } void dispaly() { int count = 0; for (int i = 0; i < CAPACITY; i++) { printf("%6d", array[i]); count++; if (count % 20 == 0) { printf("\n"); } } printf("\n"); } //插入排序 void insertSort() { const int N = 1e2; start = clock(); for (int i = 1; i < CAPACITY; i++) { int temp = array[i]; int j = i - 1; while (j >= 0) { //说明前面已经有序了 if (array[j] <= temp) { break; } //移动j的值到j+1 array[j + 1] = array[j]; j--; } array[j + 1] = temp; } end = clock(); printf("time: %f s\n", ((double)(end - start)) / CLOCKS_PER_SEC / N); } //希尔排序 void shellSort() { const int N = 1e2; start = clock(); int gap = CAPACITY / 2; while (gap > 0) { shell( gap); gap /= 2; } end = clock(); printf("time: %f s\n", ((double)(end - start)) / CLOCKS_PER_SEC / N); } void shell( int gap) { for (int i = gap; i < CAPACITY; i++) { int temp = array[i]; int j = i - gap; while (j >= 0) { if (array[j] <= temp) { break; } array[j + gap] = array[j]; j -= gap; } array[j + gap] = temp; } } void swap(int left, int right) { int temp = array[left]; array[left] = array[right]; array[right] = temp; } //冒泡排序 void bubbleSort() { const int N = 1e2; start = clock(); for (int i = 0; i < CAPACITY - 1; i++) { int set = 0; for (int j = 0; j < CAPACITY - 1 - i; j++) { if (array[j] > array[j + 1]) { swap(j, j + 1); set = 1; } } if (set==0) { break; } } end = clock(); printf("time: %f s\n", ((double)(end - start)) / CLOCKS_PER_SEC / N); } //快速排序 void quickSort() { const int N = 1e2; start = clock(); quickSortProcess(0, CAPACITY - 1); end = clock(); printf("time: %f s\n", ((double)(end - start)) / CLOCKS_PER_SEC / N); } //核心代码 void quickSortProcess(int left, int right) { if (left>=right) { return; } //找基准 int pivot= partitionHole(left, right); quickSortProcess(left, pivot); quickSortProcess( pivot+1,right); } int partitionHole(int left, int right) { int pivotValue = array[left]; while (left < right) { while (right > left && array[right] >= pivotValue) { right--; } array[left] = array[right]; while (left < right && array[left] <= pivotValue) { left++; } array[right] = array[left]; } array[left] = pivotValue; return left; } //选择排序 void selectSort() { const int N = 1e2; start = clock(); int left = 0; int right = CAPACITY - 1; while (left < right) { int minIndex = left; int maxIndex = left; //找最大值和最小值 for (int i = left + 1; i <= right; i++) { if (array[i] < array[minIndex]) { minIndex = i; } if (array[i] > array[maxIndex]) { maxIndex = i; } } if (left != minIndex) { swap(left, minIndex); } if (left == maxIndex) { minIndex = maxIndex; } if (right != maxIndex) { swap(right, maxIndex); } left++; right--; } end = clock(); printf("time: %f s\n", ((double)(end - start)) / CLOCKS_PER_SEC / N); } //归并排序 void mergeSort() { const int N = 1e2; start = clock(); mergeSortProcessor( 0, CAPACITY - 1); end = clock(); printf("time: %f s\n", ((double)(end - start)) / CLOCKS_PER_SEC / N); } void mergeSortProcessor(int left, int right) { //1、终止条件 if (left >= right) { return; } //2、找中间下标 int mid = (left + right) / 2; //3、分解左右区段 mergeSortProcessor( left, mid); mergeSortProcessor( mid + 1, right); //4、合并 marge( left, mid, right); } void marge(int left, int mid, int right) { //1、创建临时数组 //int n = (right - left + 1); int *temp=(int*)malloc((right - left + 1)*sizeof(int)); int index = 0; //2、确定每个小数组的下标 int start1 = left; int end1 = mid; int start2 = mid + 1; int end2 = right; //3、合并 while (start1 <= end1 && start2 <= end2) { if (array[start1] < array[start2]) { temp[index++] = array[start1++]; } else { temp[index++] = array[start2++]; } } //剩余元素添加到temp中 while (start1 <= end1) { temp[index++] = array[start1++]; } while (start2 <= end2) { temp[index++] = array[start2++]; } //4、temp写到原数组中 for (int i = 0; i < index; i++) { array[i + left] = temp[i]; } free(temp); temp = NULL; }
main.c
#include"sort.h" void menu() { printf("+===================================+\n"); printf("+ 欢迎使用综合排序系统 +\n"); printf("+ 1.插入排序 +\n"); printf("+ 2.希尔排序 +\n"); printf("+ 3.冒泡排序 +\n"); printf("+ 4.快速排序 +\n"); printf("+ 5.选择排序 +\n"); printf("+ 6.归并排序 +\n"); printf("+ 0.退出程序 +\n"); printf("+===================================+\n"); } void setting() { system("color 0b"); } int main() { setting(); while (1) { int select; //生成随机数组 initArray(); //dispaly(); menu(); printf("请选择需要进行的操作:"); scanf("%d", &select); switch (select) { case 1: insertSort(); save("插入排序"); system("pause"); system("cls"); break; case 2: shellSort(); save("希尔排序"); system("pause"); system("cls"); break; case 3: bubbleSort(); save("冒泡排序"); system("pause"); system("cls"); break; case 4: quickSort(); save("快速排序"); //dispaly(); system("pause"); system("cls"); break; case 5: selectSort(); save("选择排序"); system("pause"); system("cls"); break; case 6: mergeSort(); save("归并排序"); system("pause"); system("cls"); break; case 0: printf("拜拜,欢迎下次使用.....\n"); return 0; break; default: printf("选择无效,请重新选择!!!\n"); system("pause"); system("cls"); break; } } }