-------------------------------------资源来源于网络,仅供自学使用,如有侵权,联系我必删.
第一:
算法效率的度量
? 事前分析估算
依据统计的方法对算法效率进行估算
? 影响算法效率的主要因素
算法采用的策略和方法
问题的输入规模
编译器所产生的代码
计算机执行速度
第二:
算法效率的简单估算
二重循环估算
#include <stdio.h>
//(n*n + 4)T
int func(int a[], int len)
{
// 3次
int i = 0;
int j = 0;
int s = 0;
//n*n
for(i=0; i<len; i++)
{
for(j=0; j<len; j++)
{
s += i*j;
}
}
//1
return s;
}
int main()
{
int array[] = {1, 2, 3, 4, 5};
//估算func函数的操作数量
printf("%d\n", func(array, 5));
return 0;
}
? 启示
上面的程序关键部分的操作数量为n*n
随着问题规模n 的增大 , 它们操作数量的差异会越来越大 , 因此实际算法在时间效率上的差异也会变得非常明显 !
第三:
时间复杂度:
? 大O 表示法
算法效率严重依赖于操作(Operation) 数量
在判断时首先关注操作数量的最高次项
操作数量的估算可以作为时间复杂度的估算
O(5) = O(1)
O(2n + 1) = O(2n) = O(n)
O(n 2 + n + 1) = O(n 2 )
O(3n 3 +1) = O(3n 3 ) = O(n 3 )
时间复杂度:
#include <stdio.h>
int search(int array[], int length, int n)
{
int ret = -1;
int i = 0;
for(i=0; i<length; i++)
{
if( array[i] == n )
{
ret = i;
break;
}
}
return ret;
}
int main()
{
int array[5] = {1, 2, 3, 4, 5};
printf("%d\n", search(array, 5, 1)); //最好情况执行1次,复杂度o(1)
printf("%d\n", search(array, 5, 5)); //最坏情况执行n次,复杂度o(n)
return 0;
}
在没有特殊说明时,我们所分析的算法的时间复杂度都是指最坏时间复杂度
第四:
算法的空间复杂度
? 算法的空间复杂度通过计算算法的存储空间实现
S(n ) = O(f(n ))
其中 ,n 为问题规模 , f(n) 为在问题规模为n 时所占用存储空间的函数
大O 表示法同样适用于算法的空间复杂度
当算法执行时所需要的空间是常数时 , 空间复杂度为 O(1)
空间复杂度估算
#include <stdio.h>
#include <malloc.h>
//4*n+12 byte
long sum1(int n)
{
long ret = 0; //4 byte
int* array = (int*)malloc(n * sizeof(int)); //指针4 + 堆空间n*4
int i = 0; //4
for(i=0; i<n; i++)
{
array[i] = i + 1;
}
for(i=0; i<n; i++)
{
ret += array[i];
}
free(array);
return ret;
}
//8 byte
long sum2(int n)
{
long ret = 0; //4 byte
int i = 0; //4
for(i=1; i<=n; i++)
{
ret += i;
}
return ret;
}
//4 byte
long sum3(int n)
{
long ret = 0; //4 byte
if( n > 0 )
{
ret = (1 + n) * n / 2;
}
return ret;
}
int main()
{
printf("%d\n", sum1(100));
printf("%d\n", sum2(100));
printf("%d\n", sum3(100));
return 0;
}
三种求和算法中求和的关键部分的操作数量分别为2n, n 和1
时间复杂度分别为o(n),o(n)和o(1)
空间复杂度分别为o(n),o(1)和o(1)
第五:
空间与时间的策略
? 多数情况下 , 算法执行时所用的时间更令人关注
? 如果有必要 , 可以通过增加空间复杂度来降低时间复杂度
? 同理 , 也可以通过增加时间复杂度来降低空间复杂度
在实现算法时
需要分析具体问题对执行时间和空间的要求
空间换时间
#include <stdio.h>
/*
问题:
在一个由自然数1-1000中某些数字所组成的数组中,每个数字可能出现零次或者多次。
设计一个算法,找出出现次数最多的数字。
*/
//时间复杂度O(n)
void search(int a[], int len)
{
//3
int sp[1000] = {0};
int i = 0;
int max = 0;
//遍历a[]数组,如果里面是1则sp[]对应的第一位(sp[0])就加1
for(i=0; i<len; i++) //n
{
int index = a[i] - 1;
sp[index]++;
}
//遍历数组sp[] 找到最大值
for(i=0; i<1000; i++) //1000
{
if( max < sp[i] )
{
max = sp[i];
}
}
//打印满足最大值的数
for(i=0; i<1000; i++) //1000
{
if( max == sp[i] )
{
printf("%d\n", i+1);
}
}
}
int main()
{
int array[] = {1, 1, 3, 4, 5, 6, 6, 6, 2, 3};
search(array, sizeof(array)/sizeof(*array));
return 0;
}