一、实验目的:
1、为了使学生在课堂学习的同时,通过一系列的实验,使学生加深理解和更好地掌握算法时间复杂度分析方法;
2、掌握递归算法时间复杂度的递归计算过程。
二、使用仪器、器材
微机一台
操作系统:Win7
编程软件:C/C++
三、实验内容及原理
填入自己的内容(思路或算法流程图、源代码、说明等)
1、算法1
i=1;
while(i<=n)
i=i*3;
2、算法2
int factorial( int n ) {
if ( n <= 1 ) {
return 1;
} else {
return n * factorial( n – 1 );
}
}
3、算法3
void sort( int * array, int n ) {
if ( n <= 1 ) {
return; // special case: 0 or 1 items are always sorted
}
int posn = 0; // assume the first entry is the smallest
int max = array[posn];
for ( int i = 1; i < n; ++i ) { // search through the remaining entries
if ( array[i] > max ) { // if a larger one is found
posn = i; // update both the position and value
max = array[posn];
}
}
int tmp = array[n - 1]; // swap the largest entry with the last
array[n - 1] = array[posn];
array[posn] = tmp;
sort( array, n – 1 ); // sort everything else
}
问题1:用C/C++编程语言实现上述算法;
问题2:分析上述算法的时间复杂度;
问题3:绘制不同输入情况下,即n=10、100、1000、10000时的理论分析时间曲线图和算法实际运行的时间曲线。
- 实验过程原始数据记录
截屏及解读
#include <iostream>
#include <chrono>
#include <ctime>
using namespace std;
//算法1
int comp(int n)
{
typedef std::chrono::high_resolution_clock Clock;
auto start = Clock::now();//计时开始
int num = 0, i = 1;
while (i <= n)
{
i = i * 3;
++num; //运行次数
cout << i << " ";
}
cout << endl;
auto end = Clock::now();//计时结束
cout << "\n算法1运行所需时间为:" << std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count() << "ns" << '\n';
return num;
}
//算法2
static int num = 0;
int factorial(int n)
{
if (n <= 1)
{
num++;
return 1;
}
else
{
num++;
return n * factorial(n - 1);
}
}
//算法3
void sort(int* array, int n)
{
if (n <= 1)
return; // special case: 0 or 1 items are always sorted
int posn = 0; // assume the first entry is the smallest
int max = array[posn];
for (int i = 1; i < n; ++i) // search through the remaining entries
{
if (array[i] > max) // if a larger one is found
{
posn = i; // update both the position and value
max = array[posn];
}
}
int tmp = array[n - 1]; // swap the largest entry with the last
array[n - 1] = array[posn];
array[posn] = tmp;
sort(array, n - 1); // sort everything else
}
int main()
{
int n = 0;
printf("请输入n:");
scanf_s("%d", &n);
srand(time(0)); //设置时间种子
int* arr = new int[n];
for (int i = 0; i < n; i++)
{
arr[i] = rand() % 10000;
/*cout << arr[i] << " ";
if ((i + 1) % 10 == 0)
cout << endl;*/
}
cout << "算法1运行次数为:" << comp(n) << endl;
typedef std::chrono::high_resolution_clock Clock;
auto start = Clock::now();//计时开始
factorial(n);
auto end = Clock::now();//计时结束
cout << "\nfactorial所需时间为:" << std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count() << "ns" << '\n';
cout << "factorial运行次数为:" << num << endl;
typedef std::chrono::high_resolution_clock Clock;
auto start1 = Clock::now();//计时开始
sort(arr, n);
auto end1 = Clock::now();//计时结束
cout << "\nsort所需时间为:" << std::chrono::duration_cast<std::chrono::nanoseconds>(end1 - start1).count() << "ns" << '\n';
delete[]arr;
return 0;
}
五、实验结果及分析
分析:
问题2:分析上述算法的时间复杂度
算法1:
3^f(n) = n ,得f(n)=log3(n)
则其时间复杂度为O(log3(n))。
算法2:
T(n):当n=1,为O(1) ; 当n>1 , 为 T( n-1 ) + 1。
得时间复杂度为O(n)。
算法3:
sort是一个递归排序过程。
当n=1时,T(n)=1
当n>1时
T(n)=T(n-1)+n
=(T(n-2)+n-1)+n
=(T(n-3)+(n-2))+(n-1)+n
……
=(T(1)+2)+3+4+...+n
=1+2+...+n-1+n
=n(n+1)/2
=O(n²)
总结
每一次运行的时间都不一样,有一定的波动。
查找了一些资料,其原因可能是:①与操作系统的调度有关 ②现在的CPU支持动态调频。
不过算法运行的时间随着规模的增大而增大,其趋势与理论运算时间复杂度的增长趋势大致相同。由于规模数有限,只能看出比较片面的趋势。