0
点赞
收藏
分享

微信扫一扫

算法开销及曲线绘制(C语言实现)

yundejia 2022-03-13 阅读 36
c语言

算法设计与分析要求:

1、利用计算机程序设计语言,实现三种或以上的排序算法。

2、分析排序算法开销,绘制开销函数曲线。

3、比较排序算法实际运行时间和理论开销之间的差异。

这里我选择的算法是快速排序,折半排序和冒泡排序

(冒泡排序当时脑抽命名maopsort哈哈哈,已经被嘲笑了)

并且要求图线在代码中显示,不得使用excel绘图,所以需要先安装EasyX

直接搜索然后去官网下就行

在写的过程也参考了很多博主的文章,然后自己加了一点来实现自己的需求

然后写一些实现过程中的小细节

总代码如下,比较简单

定义的w是算效率的n的最大值,这里可以根据自己的需求更改,但是建议不要太大,不然电脑算不过来;

注意要让窗口和控制台同时显示时,可以先#define SHOWCONSLOE,为1为0都可以,只要在initgraph()时第三个参数使用就行,当然也可以不define,直接在第三个参数位置使用SHOWCONSLE也可以,这是我参考了别的说法,大家可以试试。

还有在做时间循环时,这里我使用了a[]和b[],主要是想让每次循环时候的数组值回复为原来的乱序状态,不然它排序一次后数组全都是排好的,这样时间就有偏差;

然后数组的获得方式使用了随机数,这是同学给我的方法,不然得自己一个个输入数,这不得疯掉;

窗口输入任意键时,因为无法使用getch(),所以使用了system("pause"),原理一样,只不过getch和conio.h冲突

然后我也不是很确定的是在图形放大时候,y和x到底是等比放大还是要按照函数的变化而变化,这里我还绕不出来,按理来说对于y=x^2时,当x=2时y=4,但是x=20时y=400,就是需要乘两次参数,这样说明它在坐标轴不能等比放大。

写的时候才发现我的理想开销没改过来,参考的同学可以注意一下,选不选择等比放大还是看自己理解吧。我的代码还是按函数关系放大了
 

#define SHOWCONSOLE	1		// 创建图形窗口时,保留控制台的显示
#include <iostream>
#include <conio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <graphics.h>		// 引用 EasyX 绘图库头文件

#define s 30 //这是一个比率,相当于我把图形放大30倍
#define w 20
   int a[w];
   int b[w];
void getb(int n)
{
    srand((unsigned)time(NULL));
    for (int i = 0; i < n; i++)
        b[i]= rand() % 100+1;
}//用来生成随机数
void quicksort(int left, int right) {
    int i, j, temp, k;
    if (left > right) {
        return;
    }
    temp = a[left];
    i = left;
    j = right;
    while (i != j) {
        while (a[j] >= temp && i < j) {
            j--;
        }
        while (a[i] <= temp && i < j) {
            i++;
        }
        if (i != j) {
            k = a[i];
            a[i] = a[j];
            a[j] = k;
        }
    }
    a[left] = a[i];
    a[i] = temp;
    quicksort(left, i - 1);
    quicksort(i + 1, right);

}
void insertsort(int a[], int n)
{
    for (int i = 1; i < n; i++) {
        if (a[i] < a[i - 1]) {//若第 i 个元素大于 i-1 元素则直接插入;反之,需要找到适当的插入位置后在插入。
            int j = i - 1;
            int x = a[i];
            while (j > -1 && x < a[j]) {  //采用顺序查找方式找到插入的位置,在查找的同时,将数组中的元素进行后移操作,给插入元素腾出空间
                a[j + 1] = a[j];
                j--;
            }
            a[j + 1] = x;      //插入到正确位置
        }

    }
}
void maopsort(int a[], int n)
{
    int i;  //比较的轮数
    int j;  //每轮比较的次数
    int buf;  //交换数据时用于存放中间数据
    for (i = 0; i < n - 1; ++i)  //比较n-1轮
    {
        for (j = 0; j < n - 1 - i; ++j)  //每轮比较n-1-i次,
        {
            if (a[j] > a[j + 1])
            {
                buf = a[j];
                a[j] = a[j + 1];
                a[j + 1] = buf;
            }
        }
    }
}
void print(int n,double q[],double e[],double m[])
{
    printf("\n%d\n排序前:", n);
    for (int i = 0; i < n; i++) {
        printf("%d  ", b[i]);
    }
    int la = 1000000;      //放大系数
    double total_t;
    int i;
   
        //快排
        clock_t start_t, end_t;
        start_t = clock();
        for (i = 0; i < la; i++)
        {
            for (int j = 0; j< n; j++)
                a[j] = b[j];
            quicksort(0, (n - 1));
        }
        end_t = clock();
        total_t = (double)(end_t - start_t)/ CLOCKS_PER_SEC;
        q[n] = total_t ;
        printf("\n排序后:");
        for (int i = 0; i < n; i++) {
            printf("%d  ", a[i]);
        }//简单输出一下排序结果
        printf("\n 快速排序耗时 %f s;",  total_t);

        //折半排序
        start_t = clock();
        for (i = 0; i < la; i++)
        {
            for (int j = 0; j < n; j++)
                a[j] = b[j];
            insertsort(a, n);
        }
        end_t = clock();
        total_t = (double)(end_t - start_t)/ CLOCKS_PER_SEC;
        e[n] = total_t;
        printf("  折半排序耗时 %f s;",  total_t);

        //冒泡排序
        start_t = clock();
        for (i = 0; i < la; i++)
        {
            for (int j = 0; j < n; j++)
                a[j] = b[j];
            maopsort(a, n);
        }  //分别代入三个函数
      
        end_t = clock();
        total_t = (double)(end_t - start_t)/CLOCKS_PER_SEC;
        m[n] = total_t;
        printf("  折半排序耗时 %f s;\n",  total_t);
        
    }


int main()
{

    //输出各个n值下的运行时间
    double q[w];
    double e[w];
    double m[w];
    
    for (int j = 0; j <w; j++) {
        getb(j);
      print(j,q,e,m); 
    }
   
    initgraph(600, 600,1);  //初始化窗口,也就是程序框大小
    setbkcolor(WHITE);      //设置背景颜色
    setlinecolor(RED);    //设置坐标轴的颜色
    cleardevice();       //清除屏幕内容
    setorigin(00, 500);    //设定坐标原点
    line(00, 00, 600, 00);    //绘制X轴
    line(00, 00, 00, -500);  //绘制Y轴
    for (int i = 0; i <= 600; i++)     //绘制X坐标轴刻度值
    {
        line(s * i, 0, s * i, -10);
        if (i % 5 == 0)
            line(s * i, 0, s * i, -15);

    }
    for (int j = 0; j <= 500; j++)//绘制Y轴正坐标轴刻度值
    {
        line(0, -s * j, 10, -s * j);
        if (j % 5 == 0)
            line(0, -s * j, 15, -s * j);
    }
    for (int j = 0; j <= 100; j++)//绘制Y轴负坐标轴刻度值
    {
        line(0, s * j, 10, s * j);
        if (j % 5 == 0)
            line(0, s * j, 15, s * j);
    }
    //输出理想状态折半排序和冒泡排序图像
    double x, y;
    for (x = 0; x <= 50; x = x + 0.001)
    {
        y = x * x;        //计算出每个X对应的Y值
        putpixel(s * x, -s *s* y, BLACK);  //画出每个点
    }
    //快速排序图像
    for (x = 0; x <= 50; x = x + 0.001)
    {
        y = x * log(x) / log(2);        //计算出每个X对应的Y值
        putpixel(s * x, -s *log(s)/log(2)* y, BLUE);  //画出每个点
    }
    //实际运行时间图像
    int j;
    for (j = 0; j < w-1; j++)//快排
    {
      //根据y随x变化的关系放大
        putpixel(s * j, -s * q[j] * log(s) / log(2), BLUE);
        setlinecolor(BLUE);
        line(s*j,-s * q[j] * log(s) / log(2),s*(j+1),-s *q[j+1] * log(s) / log(2));
    }
    for (j = 0; j < w-1; j++)//折半
    {
        putpixel(s * j, -s * e[j] * s, RED);
        setlinecolor(RED);
        line(s*j, -s*s*e[j], s*(j + 1), -s*s*e[j + 1]);
    }
    for (j = 0; j < w-1; j++)//冒泡
    {
        putpixel(s * j, -s* m[j] * s, CYAN);
        setlinecolor(CYAN);
        line(s*j, -s*s*m[j], s*(j + 1),-s*s* m[j + 1]);
    }

    system("pause");
    closegraph();

    return 0;

}

举报

相关推荐

0 条评论