(1)熟练掌握几种经典排序的算法(如冒泡排序、选择排序、插入排序、希尔排序、折半插入排序、快速排序、归并排序、堆排序等)。培养综合运用所学知识,根据具体问题进行数据结构设计和算法设计的能力。
(2)熟练掌握简单的演示菜单与人机交互设计方法。
(1)用rand()函数随机产生1-1000中30000个随机数并保存在数组array[]中。
(2)运用各种排序方法对30000个随机数进行由小到大排序。
(3)将排序结果写入不同的文件中。
(4)运用测试时间clock()函数计算各种排序的时间,并得出两种排序性能好的排序方法。
(1)试描述各种排序ADT。
(2)采用数组作为存储结构,通过利用随机函数产生N个随机整数(20000个以上),并对这些数进行多种方法进行排序。
(3)至少采用三种方法实现上述问题求解(可采用的方法有冒泡排序、选择排序、插入排序、希尔排序、折半插入排序、快速排序、归并排序、堆排序)。
(4)把排序后的数据结果保存在不同的文件中.
(5)统计每一种排序方法的性能(以上机运行程序话费时间为准进行对比),找出其中两种较快的方法。
本演示程序用C语言编写,先用产生随机数函数rand()函数产生1-1000中30000个随机数,然后运用各种排序算法(如:冒泡排序、选择排序、插入排序、希尔排序、折半插入排序、快速排序、归并排序、堆排序等)对30000个随机数进行排序,最后用测试时间函数clock()函数来计算各种排序所话费的时间,以比较各种排序的性能。
(1) 输入的形式和输入值的范围:
用rand()函数产生1-1000随机正整数,并保存到数组中。即array[i]=rand()%1000+1
(2) 输出的形式:
根据不同的排序方法输出一系列有序数据,并将数据保存在各自文件中;
(3) 测试数据及预期结果:
冒泡排序:写出数据成功!读入数据成功!
1 1 1 2 2 2 2 … 998 999 999 999 1000 1000 用时:**秒
选择排序:写出数据成功!读入数据成功!
1 1 1 2 2 2 2 … 998 999 999 999 1000 1000 用时:**秒
…
…
for(i=0;i<NUM;i++){ //NUM=30000
array[i]=rand()%1000+1;
}
此程序添加了计时器,用于精确测试各种排序方法所运行的时间,以比较各种排序方法的性能。计时函数为clock(),这个函数返回从“开启这个程序进程”到“程序中调用clock()函数”时之间的CPU始终计时单元数,其中clock_t是用来保存时间的数据类型,在time.h文件中。
如程序中start = clock()表示开始计时。而finish = clock()表示结束计时,再运用duration = (double)(finish - start) / CLOCKS_PER_SEC用来计算程序的运行时间。
1.运行界面为DOS;运行软件:Visual C++ 6.0
2.首先在主控制菜单中选择操作数1-5进行各种排序,各种排序完成后,经排序后的数据会自动写入各自对应的记事本文件。然后返回主菜单选择操作数6显示各种排序方法和时间,以便比较各种排序算法性能。
#include
#include
#include
#define NUM 30000
/*全局变量*/
int array[NUM];
FILE *fp;
clock_t start, finish;
double duration;
double t1,t2,t3,t4,t5;
/*
作者:C位出道、
*/
/*为简化代码,此函数代码为公用部分*/
void same()
{
int i;
for(i=0;i<NUM;i++){
printf("%d ",array[i]);
}
printf("\n");
finish = clock(); //结束计时
duration = (double)(finish - start) / CLOCKS_PER_SEC;
printf("用时: %f seconds\n", duration);
printf("请按任意键继续...\n");
getch();
}
/*冒泡排序*/
void maopao()
{
int i,j;
start = clock(); //开始计时
srand(time(NULL));//初始化随机数
for(i=0;i<NUM;i++){
array[i]=rand()%1000+1;
}
for(i=0;i<NUM-1;i++){
for(j=0;j<NUM-1-i;j++){
if(array[j]>array[j+1]){
int temp=array[j]; //设置中间变量
array[j]=array[j+1];
array[j+1]=temp;
}
}
}
if((fp=fopen("./起泡排序.txt","w"))==NULL)
printf("文件无法打开!");
else
{
for(i=0;i<NUM;i++)
{
fprintf(fp,"%d ",array[i]);
}
}
fclose(fp);
printf("写出数据成功!\n"); //写文件
if((fp=fopen("./起泡排序.txt","r"))==NULL)
printf("文件无法打开!");
else
{
for(i=0;i<NUM;i++)
{
fscanf(fp,"%d ",&array[i]);
}
}
fclose(fp);
printf("读入数据成功!\n"); //读文件
same();
t1=duration;
}
/*选择排序*/
void xuanze()
{
int i,j,n=NUM,temp,minValue;
start = clock(); //开始计时
srand(time(NULL));
for(i=0;i<NUM;i++){
array[i]=rand()%1000+1;
}
for(i = 0; i < n - 1; i++) //第一个数到倒数第二个数
{
minValue = i; //先把最小值赋值给第一个数
for(j = i + 1; j < n; j++) //用循环实现选择i到n-1之间最小的数值
if(array[j] < array[minValue]) //如果发现比当前最小元素还小的元素,则更新记录最小元素的下标d
minValue = j;
if(minValue != i) //交换数值
{
temp = array[minValue];
array[minValue] = array[i];
array[i] = temp;
}
}
/*写数据到文件*/
if((fp=fopen("./选择排序.txt","w"))==NULL)
printf("文件无法打开!");
else
{
for(i=0;i<NUM;i++)
{
fprintf(fp,"%d ",array[i]);
}
}
fclose(fp);
printf("写出数据成功!\n");
/*读取文件中数据*/
if((fp=fopen("./选择排序.txt","r"))==NULL)
printf("文件无法打开!");
else
{
for(i=0;i<NUM;i++)
{
fscanf(fp,"%d ",&array[i]);
}
}
fclose(fp);
printf("读入数据成功!\n");
same();
t2=duration;
}
/*插入排序的基本思想:每次将一个待排序的记录,按其关键字大小插入到前面已经排好的序列中
直到全部记录插入完成为止
直接插入排序方法的基本思想:
假设待排序列的记录存放在R【1..n】中。初始时,R【1】自成1个有序区,无序区为R【2..n】,
从i=2起直到i=n为止,依次将R【i】插入当前的有序区R【1..i-1】中,生成含n个记录的有序区。
*/
/*插入排序*/
void insert()
{
int i,j,n=NUM,insertVal;
start = clock();
srand(time(NULL)); //初始化随机数
for(i=0;i<NUM;i++){
array[i]=rand()%1000+1;
}
for(i=1;i<n;i++){
insertVal=array[i]; //insertVal为准备插入的数
j=i-1; //插入的数与有序序列最后一个进行比较
while(j>=0&&insertVal<array[j]){
array[j+1]=array[j]; //下标往后移
j--;
}
array[j+1]=insertVal;
}
if((fp=fopen("./插入排序.txt","w"))==NULL)
printf("文件无法打开!");
else
{
for(i=0;i<NUM;i++)
{
fprintf(fp,"%d ",array[i]);
}
}
fclose(fp);
printf("写出数据成功!\n");
if((fp=fopen("./插入排序.txt","r"))==NULL)
printf("文件无法打开!");
else
{
for(i=0;i<NUM;i++)
{
fscanf(fp,"%d ",&array[i]);
}
}
fclose(fp);
printf("读入数据成功!\n");
same();
t3=duration;
}
/*折半插入排序*/
void binsertSort()
{
int i,j,low,high,mid,flag;
start = clock();
srand(time(NULL)); //初始化随机数
for(i=0;i<NUM;i++){
array[i]=rand()%1000+1;
}
for(i=1;i<NUM;i++){
flag=array[i]; //flag用来暂存元素
low=0;
high=i-1; //折半查找范围
while(low<=high){
mid=(low+high)/2;
if(array[mid]>array[i]){
high=mid-1; //查找左半子表
}else{
low=mid+1; //查找右半子表
}
}
for(j=i;j>low;j--){
array[j]=array[j-1]; //统一向后移动元素,空出插入位置
array[low]=flag; //插入flag中的元素
}
}
if((fp=fopen("./折半插入排序.txt","w"))==NULL)
printf("文件无法打开!");
else
{
for(i=0;i<NUM;i++)
{
fprintf(fp,"%d ",array[i]);
}
}
fclose(fp);
printf("写出数据成功!\n"); //写文件
if((fp=fopen("./折半插入排序.txt","r"))==NULL)
printf("文件无法打开!");
else
{
for(i=0;i<NUM;i++)
{
fscanf(fp,"%d ",&array[i]);
}
}
fclose(fp);
printf("读入数据成功!\n");
same();
t4=duration;
}
/*希尔排序的实质就是分组插入排序
基本思想:现将整个待排元素序列分割成若干个子序列(由相隔某个增量的元素组成)
分别进行直接插入排序,然后依次缩小增量再进行排序,待整个序列中的
元素基本有序(增量足够小时),再对全体元素进行一次直接插入排序。
因为直接插入排序在元素基本有序的情况下,效率是很高的,因此希尔排
序在时间效率上很高。
*/
/*希尔排序*/
void shell()
{
int i,j,d,x,n=NUM,a; //d表示增量
start = clock(); //开始计时
srand(time(NULL)); //初始化随机数
for(i=0;i<NUM;i++){
array[i]=rand()%1000+1;
}
d=n/2; //增量先取一半
while(d>=1) //当增量为1时退出循环
{
for(i=d;i<n;i++){
x=array[i];
j=i-d;
//进行直接插入排序
while(j>=0&&array[j]>x)
{
array[j+d]=array[j];
j=j-d;
}
array[j+d]=x; //保存数据
}
d=d/2; //增量减小2倍
}
if((fp=fopen("./希尔排序.txt","w"))==NULL)
{
printf("文件无法打开!\n");
}else{
for(i=0;i<NUM;i++){
fprintf(fp,"%d ",array[i]);
}
fclose(fp);
printf("写出数据成功!\n");
}
if((fp=fopen("./希尔排序.txt","r"))==NULL)
{
printf("文件无法打开!\n");
}else{
for(i=0;i<NUM;i++){
fscanf(fp,"%d ",&array[i]);
}
fclose(fp);
printf("读入数据成功!\n");
}
same();
t5=duration;
}
void display()
{
printf("\n\n\t\t***显示所有排序所用的时间***\n");
printf("\n\t\t冒泡排序所用时间为:%lf\n",t1);
printf("\n\t\t选择排序所用时间为:%lf\n",t2);
printf("\n\t\t插入排序所用时间为:%lf\n",t3);
printf("\n\t\t希尔排序所用时间为:%lf\n",t5);
printf("\n\t\t折半插入排序所用时间为:%lf\n",t4);
printf("\n\t\t请按任意键继续...\n");
getch();
}
void menu()
{
printf("\n\n\t\t**☆☆欢迎来到综合排序界面☆☆**\n");
printf("\t\t…………………………………………");
printf("\n\t\t1.冒泡排序(写入文件+运行时间)\n");
printf("\n\t\t2.选择排序(写入文件+运行时间)\n");
printf("\n\t\t3.插入排序(写入文件+运行时间)\n");
printf("\n\t\t4.希尔排序(写入文件+运行时间)\n");
printf("\n\t\t5.折半插入排序(写入文件+运行时间)\n");
printf("\n\t\t6.显示方法和所用时间\n");
printf("\n\t\t0.退出界面");
printf("\n\t\t…………………………………………\n");
printf("\t\t请选择操作数(0-6):");
}
/*选择菜单函数*/
void choice()
{
int key;
while(1){
menu();
scanf("%d",&key);
if(key<0||key>6){
printf("\t\t你输入有误,请重新输入!\n");
}else{
switch(key){
case 1:system("cls");
maopao();system("cls");
break;
case 2:system("cls");
xuanze();system("cls");
break;
case 3:system("cls");
insert();system("cls");
break;
case 4:system("cls");
shell();system("cls");
break;
case 5:system("cls");
binsertSort();system("cls");
break;
case 6:system("cls");
display();system("cls");
break;
case 0:exit(1);
break;
default:printf("选择操作数有误!\n");
break;
}
}
}
}
/*主函数*/
void main()
{
choice();
getch();
}
若有不足之处,请留言,感谢! 作者:C位出道、