算法设计与分析要求:
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;
}