实验一算法的时间复杂度.docx
《实验一算法的时间复杂度.docx》由会员分享,可在线阅读,更多相关《实验一算法的时间复杂度.docx(15页珍藏版)》请在冰豆网上搜索。
![实验一算法的时间复杂度.docx](https://file1.bdocx.com/fileroot1/2023-6/27/0179f4af-74b5-4baa-895c-051a5dab0b99/0179f4af-74b5-4baa-895c-051a5dab0b991.gif)
实验一算法的时间复杂度
实验一算法的时间复杂度
一、实验目的与要求
熟悉C/C++语言的集成开发环境;
通过本实验加深对算法分析基础知识的理解。
二、实验内容:
掌握算法分析的基本方法,并结合具体的问题深入认识算法的时间复杂度分析。
三、实验题
定义一个足够大的整型数组,并分别用起泡排序、简单选择排序、快速排序和归并排序对数组中的数据进行排序(按从小到大的顺序排序),记录每种算法的实际耗时,并结合数据结构中的知识对算法的时间复杂度分析进行说明。
实验数据分两种情况:
1、数组中的数据随机生成;
2、数组中的数据已经是非递减有序。
四、实验步骤
理解算法思想和问题要求;
编程实现题目要求;
上机输入和调试自己所编的程序;
验证分析实验结果;
整理出实验报告。
五、实验程序
#include
#include
usingnamespacestd;
constintn=5000;//可根据需要更改数组大小
classSort
{
public:
voidRadom();//生成一个随机数数组
voidOrder();//生成一个非递减数组
voidBubbleSort(intr[],intn);//冒泡排序
voidSelectSort(intr[],intn);//简单选择排序
intPartition(intr[],intfirst,intend);//快速排序一次划分算法
voidQuickSort(intr[],intfirst,intend);//快速排序
voidMerge(intr[],intr1[],ints,intm,intt);//一次归并排序
voidMergeSort(intr[],intr1[],ints,intt);//归并排序
inta[n];//存放随机数的数组
inta1[n];//存放非递减数据的数组
intexchange;//冒泡排序中记载每次记录交换的位置
intbound;//冒泡排序中记录无序区的最后一个记录
intindex;//简单选择排序中记录在一趟比较过程中关键码最小的记录位置
intpivot;//快速排序中的基准记录
inttemp;//用于排序中的交换
};
//==============================生成随机数组===========================
voidSort:
:
Radom()
{
//srand(unsigned(time(NULL)));
for(inti=0;ia[i]=rand()%800;//产生随机数
}
//====================================================================
//===============================生成非递减数组=========================
voidSort:
:
Order()
{
for(inti=0;ia1[i]=i;
}
//====================================================================
//================================冒泡排序=============================
voidSort:
:
BubbleSort(intr[],intn)
{
exchange=n-1;//第一趟冒泡排序的范围是r[0]到r[n]
while(exchange)
{
bound=exchange;
exchange=0;
for(intj=0;jif(r[j]>r[j+1])
{
temp=r[j+1];
r[j+1]=r[j];
r[j]=temp;
exchange=j;
}
}
}
//====================================================================
//===============================简单选择排序==========================
voidSort:
:
SelectSort(intr[],intn)
{
for(inti=0;i{
index=i;
for(intj=i+1;j<=n;j++)
{
if(r[j]index=j;
}
if(index!
=i)
{temp=r[i];
r[i]=r[index];
r[index]=temp;
}
}
}
//====================================================================
//============================快速排序一次划分算法======================
intSort:
:
Partition(intr[],intfirst,intend)
{
inti=first;
intj=end;
while(i{
while(iif(i{
temp=r[i];
r[i]=r[j];
r[j]=temp;//将较小记录换到前面
i++;
}
while(iif(i{
temp=r[i];
r[i]=r[j];
r[j]=temp;//将较大记录换到后面
j--;
}
}
returni;//i为轴值记录的最终位置
}
//====================================================================
//==============================快速排序===============================
voidSort:
:
QuickSort(intr[],intfirst,intend)
{
if(first{
pivot=Partition(r,first,end);//一次划分
QuickSort(r,first,pivot-1);//递归地对左侧子序列进行快速排序
QuickSort(r,pivot+1,end);//递归地对右侧子序列进行快速排序
}
}
//====================================================================
//============================一次归并排序=============================
voidSort:
:
Merge(intr[],intr1[],ints,intm,intt)
{
inti=s;
intj=m+1;
intk=s;
while(i<=m&&j<=t)
{
if(r[i]<=r[j])
r1[k++]=r[i++];
elser1[k++]=r[j++];
}
if(i<=m)while(i<=m)//若第一个子序列没处理完,则进行收尾处理
r1[k++]=r[i++];
elsewhile(j<=t)//若第二个子序列没处理完,则进行收尾处理
r1[k++]=r[j++];
}
//====================================================================
//============================归并排序(递归)============================
voidSort:
:
MergeSort(intr[],intr1[],ints,intt)
{
if(s==t)r1[s]=r[s];
else
{
intm=(s+t)/2;
MergeSort(r,r1,s,m);//归并排序前半个子序列
MergeSort(r,r1,m+1,t);//归并排序前半个子序列
Merge(r1,r,s,m,t);//将两个已排序的子序列归并
}
}
//====================================================================
//===============================主函数================================
intmain()
{
Sorts;
clock_tstart,end;
s.Radom();
start=clock();
s.BubbleSort(s.a,n);
end=clock();
cout<<"随机数组冒泡排序所需时间为:
"<<(double)(end-start)<<"ms"<s.Radom();
start=clock();
s.SelectSort(s.a,n);
end=clock();
cout<<"随机数组简单选择排序所需时间为:
"<<(double)(end-start)<<"ms"<s.Radom();
start=clock();
s.QuickSort(s.a,0,n-1);
end=clock();
cout<<"随机数组快速排序所需时间为:
"<<(double)(end-start)<<"ms"<s.Radom();
intb[n]={0};
start=clock();
s.MergeSort(s.a,b,0,n-1);
end=clock();
cout<<"随机数组归并排序所需时间为:
"<<(double)(end-start)<<"ms"<cout<start=clock();
s.BubbleSort(s.a1,n);
end=clock();
cout<<"非递减数组冒泡排序所需时间为:
"<<(double)(end-start)<<"ms"<s.Radom();
start=clock();
s.SelectSort(s.a1,n);
end=clock();
cout<<"非递减数组简单选择排序所需时间为:
"<<(double)(end-start)<<"ms"<start=clock();
s.QuickSort(s.a1,0,n-1);
end=clock();
cout<<"非递减数组快速排序所需时间为:
"<<(double)(end-start)<<"ms"<start=clock();
s.MergeSort(s.a1,b,0,n-1);
end=clock();
cout<<"非递减数组归并排序所需时间为:
"<<(double)(end-start)<<"ms"<return0;
}
六、实验结果
当n=1000时:
当n=3000时:
当n=5000时:
当n=7000时:
当n=9000时:
当n=11000时:
当n=13000时:
实验结果制表:
随机数组排序所需时间
随机数组
n=1000
n=3000
n=5000
n=7000
n=9000
n=11000
n=13000
冒泡排序
16
62
141
281
453
656
921
简单选择排序
0
31
62
109
203
282
391
快速排序
0
0
0
16
0
0
15
归并排序
0
0
0
0
0
15
0
非递减数组排序所花时间
非递减数组
n=1000
n=3000
n=5000
n=7000
n=9000
n=11000
n=13000
冒泡排序
0
0
0
0
0
0
0
简单选择排序
0
16
46
110
188
282
407
快速排序
0
31
47
94
172
归并排序
0
0
0
0
15
随机数组时间复杂度函数曲线:
非递减数组时间复杂度函数曲线:
七、实验分析
运行环境:
VisualC++6.0CPU:
2.53GHz内存:
1.92GB
系统:
MicrosoftWindowsXPProfessional版本2002
冒泡排序:
在最好情况下,待排序记录序列为正序,算法只执行一趟,进行了n-1次关键码的比较,不需要移动记录,时间复杂度为O(n);
在最坏情况下,待排序记录序列为反序,每趟排序在无序序列中只有一个最大的记录被交换到最终位置,故算法执行n-1趟,第i(1≤i<n)趟排序执行了n-i次关键码的比较和n-i次记录的交换,这样,关键码的比较次数为∑(n-i)=n(n-1)/2,记录的移动次数为3n(n-1)/2,因此,时间复杂度为O(n*n);
在平均情况下,冒泡排序的时间复杂度与最坏情况同数量级。
冒泡排序是一种稳定的排序方法。
简单选择排序:
在选择排序中记录的移动次数较少。
在待排序列为正序时,记录的移动次数最少,为0;第i趟排序需进行n-i次比较,而选择排序需进行n-1趟排序,总比较次数为:
∑(n-1)=n(n-1)/2=O(n*n)
所以,总的时间复杂度为O(n*n),这是简单选择排序最好、最坏、和平均的时间性能。
简单选择排序是一种稳定的排序方法。
快速排序:
在最好情况下,每次划分对一个记录定位后,该记录的左侧子序列与右侧子序列的长度相同。
在具有n个记录的序列中,对一个记录定位要对整个待划分序列扫描一遍,则所需时间为O(n)。
设T(n)是对n个记录的序列进行排序的时间,每次划分后,把待划分区间划分为长度相等的两个子序列,则有:
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小(1≤k≤n),则有:
T(n)=(∑(T(n-k)+T(k-1))+n)/n=(2∑T(k))/n+n
这是快速排序的平均时间性能,数量级也为O(nlogn)。
快速排序是一种不稳定的排序方法。
归并排序:
一趟归并排序的操作需进行[n/2h]次归并,将r[1]~r[n]中相邻的长度为h的有序序列进行两两归并,并把结果存放到r1[1]~r1[n]中。
需要耗费O(n)时间。
整个归并排序需要进行[logn]趟,所以总时间代价是O(nlogn),这是归并排序算法最好、最坏、和平均的时间性能。
归并排序是一种稳定的排序方法。