1、实验一 算法的时间复杂度实验一 算法的时间复杂度一、 实验目的与要求熟悉C/C+语言的集成开发环境;通过本实验加深对算法分析基础知识的理解。二、 实验内容:掌握算法分析的基本方法,并结合具体的问题深入认识算法的时间复杂度分析。三、 实验题定义一个足够大的整型数组,并分别用起泡排序、简单选择排序、快速排序和归并排序对数组中的数据进行排序(按从小到大的顺序排序),记录每种算法的实际耗时,并结合数据结构中的知识对算法的时间复杂度分析进行说明。实验数据分两种情况:1、数组中的数据随机生成;2、数组中的数据已经是非递减有序。四、 实验步骤理解算法思想和问题要求;编程实现题目要求;上机输入和调试自己所编的
2、程序;验证分析实验结果;整理出实验报告。五、 实验程序#include #include using namespace std;const int n=5000; /可根据需要更改数组大小class Sortpublic: void Radom(); /生成一个随机数数组 void Order();/生成一个非递减数组 void BubbleSort(int r,int n);/冒泡排序 void SelectSort(int r,int n);/简单选择排序 int Partition(int r,int first,int end);/快速排序一次划分算法 void QuickSort(
3、int r,int first,int end);/快速排序 void Merge(int r,int r1,int s,int m,int t);/一次归并排序 void MergeSort(int r,int r1,int s,int t);/归并排序 int an;/存放随机数的数组 int a1n;/存放非递减数据的数组 int exchange;/冒泡排序中记载每次记录交换的位置 int bound;/冒泡排序中记录无序区的最后一个记录 int index;/简单选择排序中记录在一趟比较过程中关键码最小的记录位置 int pivot;/快速排序中的基准记录 int temp;/用于排
4、序中的交换;/=生成随机数组=void Sort:Radom() /srand(unsigned(time(NULL); for(int i=0;in;i+) ai=rand()%800;/产生随机数/=/=生成非递减数组=void Sort:Order() for(int i=0;in;i+) a1i=i;/=/=冒泡排序=void Sort:BubbleSort(int r,int n) exchange=n-1; /第一趟冒泡排序的范围是r0到rn while(exchange) bound=exchange; exchange=0; for(int j=0;jrj+1) temp=rj
5、+1; rj+1=rj; rj=temp; exchange=j; /=/=简单选择排序=void Sort:SelectSort(int r,int n) for(int i=0;in;i+) index=i; for(int j=i+1;j=n;j+) if(rjrindex) index=j; if(index!=i) temp=ri; ri=rindex; rindex=temp; /=/=快速排序一次划分算法=int Sort:Partition(int r,int first,int end) int i=first; int j=end; while(ij) while(ij&r
6、i=rj-1) j-; /右侧扫描 if(ij) temp=ri; ri=rj; rj=temp; /将较小记录换到前面 i+; while(ij&ri=rj-1) i+; /左侧扫描 if(ij) temp=ri; ri=rj; rj=temp; /将较大记录换到后面 j-; return i; /i为轴值记录的最终位置/=/=快速排序=void Sort:QuickSort(int r,int first,int end) if(firstend) pivot=Partition(r,first,end); /一次划分 QuickSort(r,first,pivot-1); /递归地对左侧
7、子序列进行快速排序 QuickSort(r,pivot+1,end); /递归地对右侧子序列进行快速排序 /=/=一次归并排序=void Sort:Merge(int r,int r1,int s,int m,int t) int i=s; int j=m+1; int k=s; while(i=m&j=t) if(ri=rj) r1k+=ri+; else r1k+=rj+; if(i=m) while(i=m) /若第一个子序列没处理完,则进行收尾处理 r1k+=ri+; else while(j=t) /若第二个子序列没处理完,则进行收尾处理 r1k+=rj+;/=/=归并排序(递归)=
8、void Sort:MergeSort(int r,int r1,int s,int t) if(s=t) r1s=rs; else int m=(s+t)/2; MergeSort(r,r1,s,m); /归并排序前半个子序列 MergeSort(r,r1,m+1,t); /归并排序前半个子序列 Merge(r1,r,s,m,t); /将两个已排序的子序列归并 /=/=主函数=int main() Sort s; clock_t start,end; s.Radom(); start=clock(); s.BubbleSort(s.a,n); end=clock(); cout随机数组冒泡排
9、序所需时间为:(double)(end-start)msendl; s.Radom(); start=clock(); s.SelectSort(s.a,n); end=clock(); cout随机数组简单选择排序所需时间为:(double)(end-start)msendl; s.Radom(); start=clock(); s.QuickSort(s.a,0,n-1); end=clock(); cout随机数组快速排序所需时间为:(double)(end-start)msendl; s.Radom(); int bn=0; start=clock(); s.MergeSort(s.a
10、,b,0,n-1); end=clock(); cout随机数组归并排序所需时间为:(double)(end-start)msendl; coutendl; start=clock(); s.BubbleSort(s.a1,n); end=clock(); cout非递减数组冒泡排序所需时间为:(double)(end-start)msendl; s.Radom(); start=clock(); s.SelectSort(s.a1,n); end=clock(); cout非递减数组简单选择排序所需时间为:(double)(end-start)msendl; start=clock(); s
11、.QuickSort(s.a1,0,n-1); end=clock(); cout非递减数组快速排序所需时间为:(double)(end-start)msendl; start=clock(); s.MergeSort(s.a1,b,0,n-1); end=clock(); cout非递减数组归并排序所需时间为:(double)(end-start)msendl; return 0;六、 实验结果当n=1000时:当n=3000时:当n=5000时:当n=7000时:当n=9000时:当n=11000时:当n=13000时:实验结果制表:随机数组排序所需时间随机数组n=1000n=3000n=
12、5000n=7000n=9000n=11000n=13000冒泡排序1662141281453656921简单选择排序03162109203282391快速排序000160015归并排序00000150非递减数组排序所花时间非递减数组n=1000n=3000n=5000n=7000n=9000n=11000n=13000冒泡排序0000000简单选择排序01646110188282407快速排序0314794172归并排序000015随机数组时间复杂度函数曲线:非递减数组时间复杂度函数曲线:七、 实验分析 运行环境:Visual C+ 6.0 CPU:2.53GHz 内存:1.92GB系统:M
13、icrosoft Windows XP Professional 版本2002冒泡排序:在最好情况下,待排序记录序列为正序,算法只执行一趟,进行了n-1次关键码的比较,不需要移动记录,时间复杂度为O(n);在最坏情况下,待排序记录序列为反序,每趟排序在无序序列中只有一个最大的记录被交换到最终位置,故算法执行n-1趟,第i(1in)趟排序执行了n-i次关键码的比较和n-i次记录的交换,这样,关键码的比较次数为(n-i)=n(n-1)/2,记录的移动次数为3n(n-1)/2,因此,时间复杂度为O(n*n);在平均情况下,冒泡排序的时间复杂度与最坏情况同数量级。冒泡排序是一种稳定的排序方法。简单选择
14、排序:在选择排序中记录的移动次数较少。在待排序列为正序时,记录的移动次数最少,为0;第i趟排序需进行n-i次比较,而选择排序需进行n-1趟排序,总比较次数为:(n-1)= n(n-1)/2=O(n*n)所以,总的时间复杂度为O(n*n),这是简单选择排序最好、最坏、和平均的时间性能。简单选择排序是一种稳定的排序方法。快速排序:在最好情况下,每次划分对一个记录定位后,该记录的左侧子序列与右侧子序列的长度相同。在具有n个记录的序列中,对一个记录定位要对整个待划分序列扫描一遍,则所需时间为O(n)。设T(n)是对n个记录的序列进行排序的时间,每次划分后,把待划分区间划分为长度相等的两个子序列,则有:
15、T(n)2T(n/2)+n 2(2T(n/4)+n/2)+n=4T(n/4)+2n 4(2T(n/8+n/4)+2n=8T(n/8)+3n nT(1)+nlogn=O(nlogn)因此,时间复杂度为O(nlogn)。在最坏情况下,待排序记录序列正序或逆序,每次划分只得到一个比上一次划分少一个记录的子序列(另一个子序列为空)。此时,必须经过n-1次递归调用才能把所有记录定位,而且第i趟划分需要经过n-i次关键码的比较才能找到第i个记录的基准位置,因此,总的比较次数为:(n-i)=n(n-1)/2=O(n*n)记录的移动次数小于等于比较次数。因此,时间复杂度为O(n*n)。在平均情况下,设基准记录的关键码第k小(1kn),则有:T(n)= ((T(n-k)+T(k-1))+n)/n=(2T(k))/n+n这是快速排序的平均时间性能,数量级也为O(nlogn)。快速排序是一种不稳定的排序方法。归并排序: 一趟归并排序的操作需进行n/2h次归并,将r1rn 中相邻的长度为h的有序序列进行两两归并,并把结果存放到r11r1n中。需要耗费O(n)时间。整个归并排序需要进行logn趟,所以总时间代价是O(nlogn),这是归并排序算法最好、最坏、和平均的时间性能。归并排序是一种稳定的排序方法。
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1