实验十三排序算法的实现
一、【实验目的】
(1) 理解插入排序算法的实现过程;
(2)理解不同排序算法的时间复杂度及适用环境;
(3)了解算法性能测试的基本方法。
二、【实验内容】
(1)以下是一个通过随机数来测试排序算法运行时间的程序,中间留出了加入排序算法的部分。其中可以通过修改RANDNUM的值来更改测试的数据量:
#include "stdio.h"
#include <stdlib.h>
#include <time.h>
#define RANDNUM 10000 //随机数的个数
void main()
{
int iRandNum[RANDNUM];//存放随机数
clock_t first,second; //记录开始和结束时间(以毫秒为单位)
int i;
for(i=0;i<RANDNUM;i++)
{//产生1万个随机数
iRandNum[i]=rand()%RANDNUM;
}
first=clock(); //开始时间
//此处加入排序程序
second=clock();//结束时间
//显示排序算法所用的时间
}
(2)从选择、交换、插入排序算法中任选至少3种排序算法(希尔排序、快速排序、堆排序三选二),在无序状态下进行多次运行,记录运行时间,并比较测试结果。
提示:在程序的实现过程中要用到以下函数,请大家在实验之前自学这几个函数的用法:
1)随机函数rand()
- 时间函数clock()
实验参考界面如下(此界面测试数据仅选用了两种算法,提交的报告以实验要求为准。):
三、实验源代码
c
#include "stdio.h"
#include <stdlib.h>
#include <time.h>
#define RANDNUM 10000 //随机数的个数
typedef int keyType;
typedef struct
{
keyType key;
}ElemType;
void InsertSort(int a[],int n)//用直接插入法对a[0]-a[n-1]排序
{
int i,j;
int temp;
for(i=0;i<n-1;i++)
{
temp=a[i+1];
j=i;
while(j>-1&&temp<a[j])
{
a[j+1]=a[j];
j--;
}
a[j+1]=temp;
}
}
//希尔排序
void ShellSort(int x[],int n,int d[],int number)
//x为待排列数组,n为数组中元素个数,d[0]-d[number-1]为希尔增量值
//number为步长序列个数
{
int i,j,k,m,span;//span为增量
int temp;
for(m=0;m<number;m++)//总共要进行number轮排序
{
span=d[m];
for(k=0;k<span;k++)
{
for(i=k;i+span<n;i+=span)
{
temp=x[i+span];
j=i;
while(j>-1&&temp<x[j])
{
x[j+span]=x[j];
j-=span;
}
x[j+span]=temp;
}
}
}
}
//快速排序
void QuickSort(int a[],int low,int high)
{
int i,j;
int temp;
i=low;
j=high;
temp=a[low];
while(i<j)
{
while(i<j&&temp<=a[j])
j--;
if(i<j)
{
a[i]=a[j];
i++;
}
while(i<j&&a[i]<temp)
i++;
if(i<j)
{
a[j]=a[i];
j--;
}
}
a[i]=temp;
if(low<i)
QuickSort(a,low,i-1);//对左端子集合进行递归
if(i<high)
QuickSort(a,j+1,high);//对右端子集合进行递归
}
int main()
{
int iRandNum[RANDNUM];//存放随机数
clock_t first,second; //记录开始和结束时间(以毫秒为单位)
int i;
for(i=0;i<RANDNUM;i++)//产生1万个随机数
{
iRandNum[i]=rand()%RANDNUM;
}
first=clock(); //开始时间
InsertSort(iRandNum,RANDNUM);//直接插入排序
second=clock();//结束时间
printf("直接插入排序:%lf seconds",(double)(second-first)/CLOCKS_PER_SEC);//显示排序算法所用的时间
printf("\n");
int d[]={5000,2500,1250,625,312,156,78,39,19,9,4,2,1};
int number=13;
first=clock();
ShellSort(iRandNum,RANDNUM,d,number);//希尔排序
second=clock();
printf("希尔排序:%lf seconds",(double)(second-first)/CLOCKS_PER_SEC);
printf("\n");
int low=0;
int high=RANDNUM;
first=clock();
QuickSort(iRandNum,low,high);//快速排序
second=clock();
printf("快速排序:%lf seconds",(double)(second-first)/CLOCKS_PER_SEC);
return 0;
}
四、实验结果
五、实验总结
1.碰到的问题和解决办法。
当使用 clock 函数测量时间时,它返回的是 CPU 所花费的时钟周期数,而不是实际的毫秒数。因此,将 clock 函数返回的结果直接除以 1000 可能会导致时间显示不准确
在 C语言中,clock 函数返回的时钟周期数的单位是CLOCKS PER SEC,它表示每秒钟的时钟周期数。因此,为了将时钟周期数转换为秒,你应该将 clock 函数返回的结果除以 CLOCKS PER SEC 而不是直接除以 1000。这样可以确保时间的显示更加准确。
所以,应该使用((double)(second - first) / CLOCKS PER SEC 来计算排序所用的时间,而不是(double)(second - first)/1000 。
2.你的收获。
快速排序算法:
首先,函数 QuickSort 接受一个整型数组 a[],以及两个整数参数 low 和 high,这两个参数表示数组的起始位置和结束位置。
在函数内部,定义了三个整型变量 i、j 和 temp,i 用于标记当前的位置,j 用于标记结束位置,temp 用于保存基准值。
选择数组中的第一个元素作为基准值,保存在 temp 中。
使用两个指针 i 和 j 分别从数组的两端向中间移动,以便找到需要交换的元素。
在 while 循环中,首先从右向左移动指针 j,直到找到一个小于等于基准值的元素。然后从左向右移动指针 i,直到找到一个大于基准值的元素。
交换 a[i] 和 a[j] 的值,然后继续移动指针 i 和 j,直到它们相遇。
将基准值 temp 放置在指针 i 所指向的位置,此时数组被分成了两部分,左边的部分都小于等于基准值,右边的部分都大于基准值。
接着对左右两部分分别进行递归调用 QuickSort 函数,直到排序完成。
希尔排序算法:
- 首先,函数 ShellSort 接受一个整型数组 x[],以及三个整数参数n、d[] 和 number,其中 n 表示数组中元素的个数,d[]表示希尔增量值,number表示步长序列的个数。
- 在函数内部,定义了五个整型变量 i、j、k、m和 span ,其中 i 用于标记当前的位置, j 用于标记前一个位置, k 用于标记起始位置, m 用于标记当前轮数, span 用于保存当前增量值。
- 在外层循环中,遍历所有的增量值,总共要进行 number 轮排序。
- 在内层循环中,遍历所有的子序列,每个子序列的起始位置为 k ,增量值为 span 。
- 对于每个子序列,使用插入排序算法进行排序。将第 i+span 个元素与前面的元素依次比较,如果小于前面的元素,则将前面的元素后移,直到找到合适的位置插入当前元素。
- 对于每个子序列,重复上述步骤,直到排序完成。
- 对下一个增量值进行排序,直到所有的增量值都被排序完成。