(1) 随机产生整数样本,进行8种排序,并比较各种排序算法的执行时间,如执行时间均为0,可考虑增大样本,如加大至5000或10000。
(2) 设计方案,修改“12.11.4 参考源程序”,对8种排序算法的数据元素比较次数和移动次数进行比较。
(3)输出8种排序算法每一趟排序的输出结果。
//
// Created by CHAO on 2021-12-27.
//
//1.(必做题)完善“参考源程序”,进行典型内部排序算法的比较。
//(1) 随机产生整数样本,进行8种排序,并比较各种排序算法的执行时间,如执行时间均为0,可考虑增大样本,如加大至5000或10000
//(2) 设计方案,修改“12.11.4 参考源程序”,对8种排序算法的数据元素比较次数和移动次数进行比较
//(3)输出8种排序算法每一趟排序的输出结果
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<time.h>
#define MAXSIZE 5000
int count1 = 0, count2 = 0; //比较次数,移动次数
int chishu1 = 0, chishu2 = 0, chishu3 = 0, chishu4 = 0; //记录排序趟数
int chishu5 = 0, chishu6 = 0, chishu7 = 0, chishu8 = 0;
typedef struct { //线性表
int *r;
int length;
} Sqlist;
void InitSqlist(Sqlist *L) { //构造一个空的线性表L
(*L).r = (int *) malloc(MAXSIZE * sizeof(int)); //分配内存
if (!(*L).r)
exit(-1);
(*L).length = 0;
}
void CreatSqlist(Sqlist *L) { //随机生成数据
int i;
srand(time(NULL));
for (i = 1; i <= 10; i++) {
L->r[i] = 1 + rand() % 100;
L->length++;
}
}
void Copylist(Sqlist L, Sqlist *L1) { ///复制顺序表供后续使用
int i;
L1->length = 0;
for (i = 1; i <= L.length; i++)
L1->r[i] = L.r[i];
L1->length = L.length;
}
void Output(Sqlist L1) { //输出顺序表
int i;
for (i = 1; i <= L1.length; i++) {
printf("%-4d", L1.r[i]);
if (i % 6 == 0)
printf("\n");
}
}
void Swap(int *e1, int *e2) { //交换两个值
int e;
e = (*e1);
(*e1) = (*e2);
(*e2) = e;
}
void BubbleSort(Sqlist *L) {
int i = 0, j = 0;
for (i = 1; i < L->length; i++)
for (j = L->length; j > i; j--)
if (L->r[j - 1] >= L->r[j]) {
count1++; //比较次数,移动次数
Swap(&L->r[j - 1], &L->r[j]);
count2++;
chishu1++;
printf("\n第%d趟排序:\n", chishu1);
Output(*L);
}
}
void ChoiceSort(Sqlist *L) {
int i, j, k;
for (i = 1; i < L->length; i++) { //第i次排序
k = i; //暂时是最小的
for (j = i + 1; j <= L->length; j++)
if (L->r[j] < L->r[k]) {
k = j; //找到最小元素下标最小元素下标为k
count1++;
}
if (k != i) {
Swap(&L->r[k], &L->r[i]);
count1++; //比较次数
count2++;
}
chishu2++;
printf("\n第%d趟排序:\n", chishu2);
Output(*L);
}
}
void InsertSort(Sqlist *L) {
int i = 0, j = 0;
int temp = 0;
for (i = 2; i <= L->length; i++) {
temp = L->r[i]; //从待插入组取出第一个元素。
j = i - 1;
while (j >= 1 && temp < L->r[j]) // j>=0对其进行边界限制。第二个为插入判断条件
{
count1++; // 比较次数
L->r[j + 1] = L->r[j]; //若不是合适位置,有序组元素向后移动
j--;
}
L->r[j + 1] = temp; //找到合适位置,将元素插入。
count2++; //移动次数
chishu3++;
printf("\n第%d趟排序:\n", chishu3);
Output(*L);
}
}
void QuickSort(Sqlist *L, int left, int right) {
int i, j, t, temp;
if (left > right)
return;
temp = L->r[left]; //temp中存的就是基准数
i = left;
j = right;
while (i != j) { //顺序很重要,要先从右边开始找
count1++;
while (L->r[j] >= temp && i < j) {
j--;
count1++;
}
while (L->r[i] <= temp && i < j)//再找右边的
{
i++;
count1++;
}
if (i < j)//交换两个数在数组中的位置
{
Swap(&L->r[i], &L->r[j]);
count2++;
count1++;
}
chishu4++;
printf("\n第%d趟排序:\n", chishu4);
Output(*L);
}
//最终将基准数归位
L->r[left] = L->r[i];
L->r[i] = temp;
QuickSort(L, left, i - 1);//继续处理左边的,这里是一个递归的过程
QuickSort(L, i + 1, right);//继续处理右边的 ,这里是一个递归的过程
}
void Shift(Sqlist *L, int low, int high) { //堆排序调整算法
int i = low, j = 2 * i; //j为i的右孩子
int tmp = L->r[i];
while (j <= high) {//j指向大孩子
count1++;
if (j < high && L->r[j] < L->r[j + 1])
j++;
count1++;
if (tmp < L->r[j]) //双亲小
{
Swap(&L->r[i], &L->r[j]); //将j调整到双亲结点
count2++;
i = j;
j = 2 * i;
count1++;
} else break;
}
}
void HeapSort(Sqlist *L) {
int i, temp;
for (i = L->length / 2; i >= 1; i--) //建立堆
Shift(L, i, L->length);
for (i = L->length; i >= 2; i--) //n-1次循环完成堆排序
{
count1++; //比较
temp = L->r[1];
L->r[1] = L->r[i];
L->r[i] = temp;
count2++; //交换
Shift(L, 1, i - 1);
chishu5++;
printf("\n第%d趟排序:\n", chishu5);
Output(*L);
}
}
void XierSort(Sqlist *L) {
int i, j, d;
int temp;
d = L->length / 2;
while (d > 0) {
count1++;
for (i = d + 1; i <= L->length; i++) {
count1++;
temp = L->r[i];
j = i - d;
while (j >= 1 && temp < L->r[j]) {
count1++;
L->r[j + d] = L->r[j];
j = j - d;
}
L->r[j + d] = temp;
count2++;
}
d = d / 2;
chishu6++;
printf("\n第%d趟排序:\n", chishu6);
Output(*L);
}
}
void erfengeban(Sqlist *L) {
int i, j, low, high, mid;
int n = L->length;
int temp;
for (i = 2; i <= n; i++) {
if (L->r[i] < L->r[i - 1]) {
count1++;
temp = L->r[i];
low = 1, high = i-1;
while (low <= high) {
count1++;
mid = (low + high) / 2;
if (temp <= L->r[mid])
high = mid - 1;
else
low = mid + 1;
count1++;
}
for (j = i - 1; j >= high + 1; j--)
L->r[j + 1] = L->r[j];
count1++;
L->r[high + 1] = temp;
count2++;
}
chishu7++;
printf("\n第%d趟排序:\n", chishu7);
Output(*L);
}
}
//归并排序
//一次二路归并函数,参数:数组,第一组初始下标,第一组结束下标,第二组结束下标
void Merge(Sqlist *arr, int low, int mid, int high) {
int i = low, j = mid + 1;//两组的初始下标
int *arr2 = (int *) malloc(sizeof(int ) * (high - low + 1));//创建临时数组
int k = 0;
while (i <= mid && j <= high) {
if (arr->r[i]< arr->r[j]) {
count1++;
count2++;
arr2[k] = arr->r[i];
i++;
k++;
} else {
count1++;
count2++;
arr2[k] = arr->r[j];
j++;
k++;
}
}
while (i <= mid) {
count1++;
count2++;
arr2[k] = arr->r[i];
i++;
k++;
count1++;
}
while (j <= high) {
count1++;
count2++;
arr2[k] = arr->r[j];
j++;
k++;
}
//将临时数组中的数据写回原数组中
int ii1, ii2;
for (ii1 = low, ii2 = 0; ii1 <=high; ii1++, ii2++) {
count2++;
arr->r[ii1] = arr2[ii2];
}
free(arr2);
}
//一趟二路归并,参数,数组,段长度,数组长度
void MergePath(Sqlist *arr, int length, int n) {
int i;
for (i = 1; i + 2 * length -1<=n; i = i + 2 * length) {
Merge(arr, i, i + length - 1, i + 2 * length - 1);
}
if (i + length -1 <=n) {//若成立,合并最后两组,且第二组的数据小于length,若没有第二组,则mid和high相等,函数内直接将第一组合并,并不影响
Merge(arr, i, i + length - 1, n);
}
}
//二路归并排序算法
void Mergesort(Sqlist *arr, int n) {
int length;
for (length = 1; length <= n; length = length * 2)
{
MergePath(arr, length, n);
chishu8++;
printf("\n第%d趟排序:\n", chishu8);
Output(*arr);
}
}
int main() {
Sqlist L, LCopy;
int select, t, flag = 1,
dlta[MAXSIZE]; //希尔排序
double timesecond;
clock_t start, finish; //记录时间
InitSqlist(&L); //创建顺序表
InitSqlist(&LCopy);
CreatSqlist(&L);
Output(L);
while (flag) {
Copylist(L, &LCopy); //复制数组供后续使用
count1 = 0;//计较次数
count2 = 0; //移动次数
printf("\n请选择:\n");
printf("1.冒泡排序 \n");
printf("2.选择排序 \n");
printf("3.插入排序 \n");
printf("4.快速排序 \n");
printf("5.堆排序 \n");
printf("6.希尔排序 \n");
printf("7.二分插入排序 \n");
printf("8.归并排序 \n");
printf("9.退出 \n");
scanf("%d", &select);
switch (select) {
case 1:
printf("\n 冒泡排序");
start = clock();
BubbleSort(&LCopy);
finish = clock();
break;
case 2:
printf("\n 选择排序");
start = clock();
ChoiceSort(&LCopy);
finish = clock();
break;
case 3:
printf("\n 插入排序");
start = clock();
InsertSort(&LCopy);
finish = clock();
break;
case 4:
printf("\n 快速排序");
start = clock();
QuickSort(&LCopy, 1, L.length);
finish = clock();
break;
case 5:
printf("\n 堆排序");
start = clock();
HeapSort(&LCopy);
finish = clock();
break;
case 6:
printf("\n 希尔排序");
start = clock();
XierSort(&LCopy);
finish = clock();
break;
case 7:
printf("\n 二分查找插入排序");
start = clock();
erfengeban(&LCopy);
finish = clock();
break;
case 8:
printf("\n 归并排序");
start = clock();
Mergesort(&LCopy,LCopy.length);
finish = clock();
break;
default:
flag = 0;
printf("退出\n");
exit(0);
getch();
}
timesecond = (double) (finish - start);
printf("\n排序花费的时间为 :%lf \n", timesecond);
printf("\n这个排序共比较%4d次,共移动元素%4d次", count1, count2);
}
return 1;
}
1.我随机生成的数据数目为10个,我给定了,排序时间也可以很清楚,不用几百或几千个数据。
2.线性表下标从1开始放入数据。
3.每次选择排序时只需要输入前面的序号来选择,会循环的让你来选择排序。