数据结构:八种排序

(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.每次选择排序时只需要输入前面的序号来选择,会循环的让你来选择排序。
在这里插入图片描述在这里插入图片描述在这里插入图片描述

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

江景.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值