算法实验1--算法排序比较


一、实验目的:

比较至少4种排序算法的执行效率。已学过的算法:起泡排序、选择排序、插入排序、shell排序,归并排序、快速排序等。

二、实验要求:

1、从中选择至少4中排序算法,写成独立的函数进行调用。

2、参与排序的数据不少于5000个,要求用数据文件存储随机产生的数据。

3、要求在main()函数中调用以上函数,并输出各排序算法所用时间。

三、问题描述:

通过至少四种排序算法设计,功能实现,计算出完成随机生成的至少5000个数所需要的时间,并比较各种算法的效率。

四、算法分析:

随机数存入文件:函数void RandToFile(int *a);通过rand()函数生成随机数,再利用文件指针*fp将生成的随机数所在的数组存入文件data.txt。

从文件读取随机数:函数void ReadFromFile(int a[]);通过文件指针*fp读文件data.txt中的数组用于后续运算。

快速排序:函数void Quick_Sort(int *a,int low,int high);采用递归思想将数组以基数为中间大小分割成两部分,在对所分割的每部分采用递归方法分割,知道每部分只有一个元素,对每个单位进行排序。快速排序是不稳定的。最理想情况算法时间复杂度O(nlog2n),最坏O(n2)

插入排序:函数void Insert_Sort(int *a,int n);假设设定的数组的前n(n>=2)个数已是有序,将第n个数插入到该有序序列中,并使之有序。如此循环反复,知道数组全部排列完成。直接插入排序是稳定的。算法时间复杂度O(n2)--[n的平方]

冒泡排序:函数void Bubble_Sort(int *a,int n);在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。冒泡排序是稳定的。算法时间复杂度O(n2)--[n的平方]

希尔排序:函数void Shell_Sort(int *a,int n);算法先将要排序的一组数按某个增量d分成若干组,每组中记录的下标相差d.对每组中全部元素进行排序,然后再用一个较小的增量对它进行,在每组中再进行排序。当增量减到1时,整个要排序的数被分成一组,排序完成。

希尔排序是不稳定的。

选择排序:函数void Select_Sort(int *a,int n);在要排序的一组数中,选出最小的一个数与第一个位置的数交换;然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止。

选择排序是不稳定的。算法复杂度O(n2)--[n的平方]

主函数:在主函数内,首先调用随机数生成并存入文件的函数,在调用从文件读取数据的函数,然后,通过包含头文件<time.h>调用时钟函数clock()记录开始执行时间和结束时间,相减得出执行时间并显示在显示器上。在主函数内,可通过修改常变量N的值生成不同个数和不同范围的随机数,已验证执行时间的精确性。

五、代码:

1.随机数存入文件(void RandToFile(int *a))

//生成N个小于N的随机数,存入数组a

void RandToFile(int *a)

{

srand( (unsigned)time( NULL ) );  //初始化随机数

for(int i=0;i<N;i++)

{

a[i]=(int)rand()%N;

}

FILE *fp;

if((fp=fopen("data.txt","w"))==NULL)

{

printf("\nerror on open data.txt!");

getch();

exit(1);

}

for(i=0;i<N;i++)

fprintf(fp,"%1d\n",a[i]);

fclose(fp);

}

2.从文件读取数据(void ReadFromFile(int a[]))

void ReadFromFile(int a[])

{

int i=0;

FILE *fp;

if((fp=fopen("data.txt","r"))==NULL)

{

printf("file read error!");

exit(1);

}

while(!feof(fp))

{

fscanf(fp,"%d",&a[i++]);

}

fclose(fp);

}

3.快速排序(void Quick_Sort(int *a,int low,int high))

void Quick_Sort(int *a,int low,int high)

{

int Partition(int *a,int low,int high);

int mid;

if(low<high)

{

mid=Partition(a,low,high);

Quick_Sort(a,low,mid-1);/*递归调用*/

Quick_Sort(a,mid+1,high);

}

}

int Partition(int *a,int low,int high)

{

int mid,temp;

int i=low,j=high+1;

mid=a[low];

while(i < j)

{

while((a[++i] < mid)&&i<high);

while(a[--j]>mid);

if(i>=j)break;

temp=a[i];

a[i]=a[j];

a[j]=temp;

}

a[low]=a[j];

return j;

}

4.插入排序(void Insert_Sort(int *a,int n))

void Insert_Sort(int *a,int n)

{

int i,j,temp;

for(i=1;i<n;i++)

{

temp=a[i];/*操作当前元素,先保存在其它变量中*/

for(j=i-1;j>=0&&a[j]>temp;j--)

{

a[j+1]=a[j];/*一边找一边移动元素*/

}

a[j+1]=temp;

}

}

5.冒泡排序(void Bubble_Sort(int *a,int n))

void Bubble_Sort(int *a,int n)

{

int i,j,temp;

for(i=0;i<n-1;i++)

for(j=0;j<n-i;j++) /*注意循环的上下限*/

if(a[j]>a[j+1])

{

temp=a[j];

a[j]=a[+1];

a[j+1]=temp;

}

}

6.希尔排序(void Shell_Sort(int *a,int n))

void Shell_Sort(int *a,int n)

{

int gap,i,j,temp;

for(gap=n/2;gap>0;gap/=2)/*设置排序的步长,步长gap每次减半*/

{

for(i=gap;i<n;i++)/*定位到每一个元素*/

{

for(j=i-gap;(j>=0)&&(a[j]>a[j+gap]);j-=gap)/*比较相距

gap远的两个元素的大小,根据排序方向决定如何调换*/

{

temp=a[j];a[j]=a[j+gap];a[j+gap]=temp;

}

}

}

}

7.选择排序(void Select_Sort(int *a,int n))

void Select_Sort(int *a,int n)

{

int i,j,k,temp;

for(i=0;i<n-1;i++)

{

k=i;

for(j=i+1;j<n;j++)

{

if(a[k]>a[j]) //a[k]若大于a[j]将j赋值给k;

k=j;

}

temp=a[i];

a[i]=a[k];

a[k]=temp;

}

}

8.主函数

void main()

{

printf("===============各种排序所耗的时间==============\n");

int a[N];

int low=0;

clock_t begin,stop;

RandToFile(a);

ReadFromFile(a);

double exeTime_Quick,exeTime_Insert,exeTime_Bubble,exeTime_Shell,exeTime_Select;

//测试快速排序时间

begin=clock();//开始记录时间

Quick_Sort(a,low,N);

stop=clock();//时间记录完成

exeTime_Quick=(double)(stop-begin)/CLOCKS_PER_SEC;

printf( "快速排序%d个整数耗时 %f 秒\n",N,exeTime_Quick);

//测试插入排序时间

begin=clock();

Insert_Sort(a,N);

stop=clock();

exeTime_Insert=(double)(stop-begin)/CLOCKS_PER_SEC;

printf( "插入排序%d个整数耗时 %f 秒\n",N,exeTime_Insert);

//测试冒泡排序时间

begin=clock();

Bubble_Sort(a,N);

stop=clock();

exeTime_Bubble=(double)(stop-begin)/CLOCKS_PER_SEC;

printf( "冒泡排序%d个整数耗时 %f 秒\n",N,exeTime_Bubble);

//测试希尔排序时间

begin=clock();

Shell_Sort(a,N);

stop=clock();

exeTime_Shell=(double)(stop-begin)/CLOCKS_PER_SEC;

printf( "希尔排序%d个整数耗时 %f 秒\n",N,exeTime_Shell);

//测试选择排序时间

begin=clock();

Select_Sort(a,N);

stop=clock();

exeTime_Select=(double)(stop-begin)/CLOCKS_PER_SEC;

printf( "选择排序%d个整数耗时 %f 秒\n",N,exeTime_Select);

printf("Input a char To end!");

getchar();//等待输入字符,不让窗口关闭

}

六、调试及运行:

1.当生成50000个随机数为参数时调试效果如下

2.当生成100000个随机数为参数时调试效果如下:

3.生成的随机数存入文件data.txt如下:

七、实验总结

通过这次算法实验,首先,我对各种排序算法的分类有了一定了解,也巩固了这些算法的基本原理;然后,在编程当中少不了算法的设计和分析,这个实验的难度让我感觉到了自身理论知识储备的不足;最后,我认为做这次实验的目的不仅仅是得到各种排序算法效率的比较,更重要的是让我们理解算法里面的思维模式,知道各种排序算法的基本原理比知道它们的效率更重要。

时间: 2024-11-03 05:27:37

算法实验1--算法排序比较的相关文章

数据结构与算法系列研究九——排序算法的一些探讨

四种排序 一.实验内容     输入20个整数,分别用希尔排序.快速排序.堆排序和归并排序实现由小到大排序并输出排序结果.二.关键数据结构与核心算法   关键数据结构:由于是排序为了简单起见,选用线性表中的数组作为存储结构.   核心算法:   1.希尔排序    希尔排序的核心还是直接插入法,但是插入的位置有所讲究.要把数组分为许多段,每一段的长度除了最后的有可能不同之外,其他的都相同.该段的长度即为增量,在最后一次必须为一,此时程序变成了直接插入.每次进行隔段插入,不断地调整是的数组变得隔段

算法实验11:还是畅通工程(最小生成树 kruscal prim)

算法实验11:还是畅通工程 Description 某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离.省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路总长度为最小.请计算最小的公路总长度. Input 测试输入包含若干测试用例.每个测试用例的第1行给出村庄数目N ( < 100 ):随后的N(N-1)/2行对应村庄间的距离,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间的距离.为简单起

【数据结构】非比较排序算法(实现计数排序和基数排序)

● 计数排序 1.算法思想: 计数排序是直接定址法的变形.通过开辟一定大小的空间,统计相同数据出现的次数,然后回写到原序列中. 2.步骤: 1)找到序列中的最大和最小数据,确定开辟的空间大小. 2)开辟空间,利用开辟的空间存放各数据的个数. 3)将排好序的序列回写到原序列中. 具体实现如下: void CountSort(int *arr, int size) {  assert(arr);  int min = arr[0];  int max = arr[0];  int num = 0;

基本算法研究1-冒泡排序算法测试

基本算法研究1-冒泡排序算法测试 1.经典冒泡排序法基本原理 先看一个动态图,感觉比较形象: 冒泡排序(Bubble Sort)是一种简单的排序算法.默认是从小到大排序,即把最大的数据排在最后,相当于每次把最大数据像气泡一样浮到水面一样.它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.走访数列的工作是重复地进行直到没有再需要交换. 基本步骤: 1.比较相邻的元素.如果第一个比第二个大,就交换他们两个.        2.对每一对相邻元素作同样的工作,从开始第一对

排序算法之归并算法

/* 本例拟在实现排序算法的归并算法,归并算法遵循分治法的思想 归并算法: 归并算法主要用来合并两个已经排好序的序列.用Merge(A,p,q,r)来实现合并, 其中A代表数组,A[p,q]和A[q+1,r]A的两个子数组,且两个数组都已经排好序,归并算法 就是将这两个子数组合并成一个排好序的数组并替代当前的数组A[p,r]. */ public class Merge { public static void main(String[] args) { int[] a = {1,2,3,4,5

排序算法(4)-线性时间排序

在前面三节排序算法中,我们分别分析了不同策略,思想用于排序,而这些算法都是基于数据间的比较来确定顺序的.假设我不用比较,换一种思路,那么就可以达到时间复杂度为O(n)的排序算法,当然是以付出额外的空间为代价的. 一.基本思想 线性时间排序的算法思想: (1):在计数排序中,利用比x小或等的元素个数和的来确定x位置.比如2 5 4 9 1 6.9比其余5个数都大,那就说明9 在排序后的第6个位置,这样我们只要得到比某个数大的元素个数就能得到元素在排序后数组中的位置了. (2):在桶排序中,是通过映

【JavaScript】【算法】JavaScript版排序算法

JavaScript版排序算法:冒泡排序.快速排序.插入排序.希尔排序(小数据时,希尔排序会比快排快哦) 1 //排序算法 2 window.onload = function(){ 3 var array = [0,1,2,44,4, 4 324,5,65,6,6, 5 34,4,5,6,2, 6 43,5,6,62,43, 7 5,1,4,51,56, 8 76,7,7,2,1, 9 45,4,6,7,8]; 10 //var array = [4,2,5,1,0,3]; 11 array

排序算法总结之希尔排序

一,希尔排序算法介绍 ①希尔排序又称缩小增量排序 ,它本质上是一个插入排序算法.为什么呢? 因为,对于插入排序而言,插入排序是将当前待排序的元素与前面所有的元素比较,而希尔排序是将当前元素与前面增量位置上的元素进行比较,然后,再将该元素插入到合适位置.当一趟希尔排序完成后,处于增量位置上的元素是有序的. ②希尔排序算法的效率依赖于增量的选取 假设增量序列为 h(1),h(2).....h(k),其中h(1)必须为1,且h(1)<h(2)<...h(k) . 第一趟排序时在增量为h(k)的各个元

【算法】简单选择排序C语言实现

上一篇我们谈到了冒泡排序,实现了两个版本的冒泡排序,不知道大家有没有对冒泡排序的特点进行一下总结呢?其实冒泡排序还算是比较暴力的,因为它频繁不断的进行交换,那么这样的话,我们的计算机的计算频率就会很高,不算是很高效,那么我们可不可以找到一种交换次数少一点的方法呢?这就引出了我们接下来要介绍的简单选择排序算法了. 简单选择排序的基本思想就是通过N-1次的关键字间的比较,从N - i + 1个记录中选择一个关键字最小记录,并和第i(1<= i <= n)个记录交换,其实简单选择排序和冒泡排序在思路