随机生成30个数,试比较直接插入排序、简单选择排序、冒泡排序、快速排序、堆排序和希尔排序的时空性能和稳定性。

来源:互联网 发布:淘宝店铺神笔在哪里 编辑:程序博客网 时间:2024/05/17 23:08

题目

随机生成30个数,试比较直接插入排序、简单选择排序、冒泡排序、快速排序、堆排序和希尔排序的时空性能和稳定性。

源代码

#include<stdio.h>#include<time.h>          //产生随机数时时钟做种子#include<stdlib.h>#define MaxSize 50typedef struct{    int key;      //记录关键字}RecordType;//直接插入排序void InsertSort(RecordType r[], int length){    for (int i = 2; i < length; i++)    {        r[0] = r[i];             //将待插入的记录放在监视哨中        int j = i - 1;        while (r[0].key < r[j].key)        {            r[j + 1] = r[j];            j = j - 1;        }        r[j + 1] = r[0];      //将待插入记录插入到已排序的序列中    }}//简单选择排序void SelectSort(RecordType r[], int length) {    int x;    //假设待排序列有n个数从第一个开始,以次与其后面的数比较,需要比较n-1次    for (int i = 1; i <= length - 1; i++)    {        int k = i;        for (int j = i + 1; j <= length; j++)  //j从2开始        {            if (r[j].key < r[k].key)            {                k = j;            }        }        if (k != i)             //当r[j].key>=r[k].key 将r[k]的值借助中间变量X与x[i]的值交换        {            x = r[i].key;               //r[i].key为最小数            r[i].key = r[k].key;            r[k].key = x;        }    }}//冒泡排序void BubbleSort(RecordType r[], int length){    int t;    for (int i = 1; i <= length; i++)    {        for (int j = 1; j <= length - i - 1; j++)        {            if (r[j].key > r[j + 1].key)            {                t = r[j+1].key;                r[j + 1].key = r[j].key;                r[j].key = t;            }        }    }}//快速排序int QKPass(RecordType r[], int left, int right) //一趟快速排序算法{    int low = left;    int high = right;    r[0] = r[left];    while (low < high)    {        while (low<high && r[high].key>r[0].key)        {            high--;        }        if (low < high)        {            r[low] = r[high];            low++;        }        while (low < high && r[low].key < r[0].key)        {            low++;        }        if (low < high)        {            r[high] = r[low];            high--;        }    }    r[low] = r[0];    return low;               //返回基准记录的位置}void QKSort(RecordType r[], int low, int high)      //快速排序{    if (low < high)    {        int pos = QKPass(r, low, high);         //调用一趟快速排序,以枢轴元素为界划分两个子区间        QKSort(r, low, pos - 1);             //对左部子表进行快速排序        QKSort(r, pos + 1, high);             //对右部子表进行快速排序    }}//堆排序void sift(RecordType r[], int n, int m){//对编号为m的节点进行调整    int i = m;    r[0] = r[i];    int j = 2 * i;    while (j <= n)    {        if (j < n && r[j].key<r[j + 1].key)        {            j = j + 1;        }        if (r[j].key>r[0].key)        {            r[i] = r[j];            i = j;            j = 2 * i;        }        else        {            break;        }    }    r[i] = r[0];}void HeapSort(RecordType r[], int length){    //初建堆    int i;    for (i = length / 2; i > 0; i--)    {        sift(r, length, i);    }    //调整    for (i = length; i > 1; i--)    {        r[0] = r[1];        r[1] = r[i];        r[i] = r[0];        sift(r, i - 1, 1);    }}//希尔排序void ShellInsert(RecordType r[], int length, int delta)  //Shell插入,其中delta 为增量{    int i, j;    for (i = 1 + delta; i <= length; i++)    {        if (r[i].key < r[i - delta].key)        {            r[0] = r[i];          //备份r[i](不做监视哨)            for (j = i - delta; j > 0 && r[j].key > r[0].key; j -= delta)            {                r[j + delta] = r[j];            }            r[j + delta] = r[0];        }    }}void ShellSort(RecordType r[], int length, int delta[], int n)//希尔排序,delta为增量数组,n为增量数组长度{    for (int i = 0; i < n; i++)    {        ShellInsert(r, length, delta[i]);    }}void ShowResult(RecordType* r, int length)        //输出结果{    for (int i = 1; i <= length; i++)    {        printf("%d\t", r[i]);        if (i % 10 == 0)        {            printf("\n");        }    }}void RandNum(RecordType r[MaxSize]){    srand((unsigned)time(NULL)); //初始化随机数    for (int i = 1; i <= 30; i++)          {        r[i].key = rand() % 100 + 1;       //产生1-100之间的随机数        printf("%d\t", r[i]);        if (i % 10 == 0)                    //每行输出10个数        {            printf("\n");        }    }}void Select(){    printf("------------排序算法-----------\n");    printf("* * * * 1:直接插入排序 * * * *\n");    printf("* * * * 2:简单选择排序 * * * *\n");    printf("* * * * 3:  冒泡排序   * * * *\n");    printf("* * * * 4:  快速排序   * * * *\n");    printf("* * * * 5:   堆排序    * * * *\n");    printf("* * * * 6:  希尔排序   * * * *\n");    printf("-------------------------------\n");}int main(void){    int n, m;    RecordType r[31] ;    /*delta[] 是希尔排序的增量数组。增量的选取采用的是希尔提出的d=n/2 向下取整,    直到d=1为止的方法,随机产生30个数30/2=15、15/2=7(向下取整的结果)、依次运算    得到增量数组元素为15、7、3、1 */    int delta[] = { 15, 7, 3, 1 };     Select();    do    {        printf("请选择排序算法:");        scanf("%d", &m);        system("cls");      //清屏        switch (m)        {        case 1:            printf("你选择了直接插入排序!\n");            printf("\n");            printf("产生的随机待排序列为:\n");            RandNum(r);            InsertSort(r, 30);            printf("排序结果为:\n");            ShowResult(r, 30);            break;            system("cls");        case 2:            printf("你选择了简单选择排序!\n");            printf("\n");            printf("产生的随机待排序列为:\n");            RandNum(r);            SelectSort(r, 30);            printf("排序结果为:\n");            ShowResult(r, 30);            break;        case 3:            printf("你选择了冒泡排序!\n");            printf("\n");            printf("产生的随机待排序列为:\n");            RandNum(r);            BubbleSort(r, 30);            printf("排序结果为:\n");            ShowResult(r, 30);            break;        case 4:            printf("你选择了快速排序!\n");            printf("\n");            printf("产生的随机待排序列为:\n");            RandNum(r);            QKSort(r, 1, 29);            printf("排序结果为:\n");            ShowResult(r, 30);            break;        case 5:            printf("你选择了堆排序!\n");            printf("\n");            printf("产生的随机待排序列为:\n");            RandNum(r);            HeapSort(r, 30);            printf("排序结果为:\n");            ShowResult(r, 30);            break;        case 6:            printf("你选择了希尔排序!\n");            printf("\n");            printf("产生的随机待排序列为:\n");            RandNum(r);            ShellSort(r, 30, delta, 4);            printf("排序结果为:\n");            ShowResult(r, 30);            break;        default:            printf("输入有误!");            return false;            break;        }    } while (true);    return 0;}

时空性能和稳定性

时空性能和稳定性如下表

排序算法 平均时间复杂度 最坏时间复杂度 空间复杂度 稳定性 直接插入排序 O(n) O(n^2) O(1) 稳定 简单选择排序 O(n^2) O(n^2) O(1) 不稳定 冒泡排序 O(n^2) O(n^2) O(1) 稳定 快速排序 O(nlog_2,n) O(n^2) O(nlog_2,n) 不稳定 堆排序 O(nlog_2,n) O(nlog_2,n) O(1) 不稳定 希尔排序 O(n^(3/2)) O(1) 不稳定

简要分析

这道题是数据结构-用C语言表示(耿国华 主编)课本第九章 内部排序 课后实习题第一题,当时大二上数据结构时上机偏向随机产生30个数采用题目要求的排序算法:直接插入排序、简单选择排序、冒泡排序、快速排序、堆排序和希尔排序实现对产生的随机数进行排序,再次回顾数据结构这本书,刚好看到这道题,就简单的写了一下,依然偏重产生随机数进行排序,也算是对排序算法的回顾。

这是一道相对简单的编程题,只需要理解排序算法的实现过程,用代码实现,然后利用已有的C语言知识,将代码合理组合起来就可以了。

值得注意的是题目要求随机生成随机数,这就需要使用产生随机数的函数,产生随机数的方法很多,在上面的代码中主要利用rand() 函数,以时间为种子产生随机数,每一次执行程序语句的时间是不同的,所以可以产生不同的随机数,将产生随机数的代码写成函数,具体函数如下:

void RandNum(RecordType r[MaxSize]){    srand((unsigned)time(NULL)); //初始化随机数    for (int i = 1; i <= 30; i++)          {        r[i].key = rand() % 100 + 1;       //产生1-100之间的随机数        printf("%d\t", r[i]);        if (i % 10 == 0)                    //每行输出10个数        {            printf("\n");        }    }}

由于以时间做种子,使用了srand()函数和rand()函数,所以需要包含头文件
<#include “stdlib.h” 和# include “time.h”;

在代码中定义了Select()函数,用于提示用户输入选择,在do -while 语句前调用Select()函数,所以只在在第一次执行时输出提示选择菜单信息,后面的代码中使用了system(“cls”); 进行清屏,确保每次只显示当前产生的随机数和排序结构,提示用户输入选择。
使用switch() 语句,并通过函数调用实现,由于每次都调用定义的函数RandNum(RecordType r[MaxSize]),所以每次进行排序的序列,都是不同的随机数序列。然后,根据用户输入的选择进行相应函数调用,完成排序。通过调试,程序可以成功运行,并实现相应功能。

阅读全文
1 0