备注:文章仅用于个人学习记录,严禁任何形式的转载。
备注:本人初学者,欢迎任何善意的指导和交流,非常感谢。
1.浅谈算法但不一定准确
算法个人理解:解决一件事情的方法,所谓方法是解决问题时你的思考所形成方案。
比如:想吃饭,有做饭,点外卖,堂食三种方案,都可以满足需求,但是当你有选择的时候你肯定想选一个最适合自己的,这就牵扯到方案的评价,最后得到最有益的方案。对于算法来说,这种评价也是非常必要的。因为我们需要最有益的方案。
2.评价算法的优劣
在算法正确且鲁棒性好的基础上,我们通常用时间复杂度和空间复杂度来评价,当然还有事后统计法等其它方法。什么是时间和空间复杂度呢?
2.1时间复杂度
时间复杂度并不是指程序运行了几秒,几微米这种时间单位,因为不同的计算机的性能是不一样的,所以不会这么评价。(目前是这样理解的)时间复杂度:是指程序最多运行的次数。而且这个次数仅仅是用量级衡量的,譬如1,n,n²,用大O表示。如O(1),O(n)。
复杂度 | 表示 |
---|---|
常数阶 | O(1) |
对数阶 | O(logn) |
线性阶 | O(n) |
平方阶 | O(n²) |
常数阶:程序顺序执行不会随着变量规模增加而增加阶数。
arrayExample[100] = {1, 2, 3};
std:: cout << arrayExample[1] << std::endl; //line 2
std:: cout << arrayExample[99] << std::endl; //line 3
第二行和第三行的量级是一样的,都是常数阶,不会因为索引更大而改变程序的时间复杂度。
对数阶和线性阶:对数阶放在二分法中理解,当我们需要在一个数组中查找一个特定的值时,我们通常会采用二分法查找,来节省程序的运行时间,但有时我们也会顺序比对数组中的值来查找元素。
int main(void)
{
int BisectionMethodArray[10] = {1, 2, 3, 4, 4, 4, 4, 4, 4, 5};
int times = 0; //记录程序运行次数
for(int i = 0; i < 10; i++)
{
times++;
if(BisectionMethodArray[i] == 5)
{
;
}
}
std::cout << times << std::endl;
return 0;
}
这是一个顺序查找的例子,可以看出,当数组内元素个数为10时,程序执行了10次,如果程序为10000呢?毫无疑问的是它会执行一万次来找到所有为5的元素。所以它的时间复杂度为O(n)。
现在我们利用二分法查找我们想要的元素,看时间复杂度是否会降低。
#include <iostream>
#define ARRAYNUM 5
#define FINDNUM 2
int main(void)
{
int BisectionMethodArray[ARRAYNUM] = {1, 2, 3, 4, 5};
int times = 0; //记录程序运行次数
int indexArrayHead = 4, indexArrayTail = 0, temp;
while(1)
{
times++;
if((indexArrayHead + indexArrayTail) %2 != 0)
{
temp = (indexArrayHead + indexArrayTail + 1)/2;
}
else
{
temp = (indexArrayHead + indexArrayTail)/2;
std::cout << temp << std::endl;
}
if(BisectionMethodArray[temp] == FINDNUM)
{
break;
}
else if(BisectionMethodArray[temp] < FINDNUM)
{
indexArrayTail = temp;
}
else if(BisectionMethodArray[temp] > FINDNUM)
{
indexArrayHead = temp;
}
std::cout << indexArrayHead << " " << indexArrayTail << " " << times << std::endl;
}
return 0;
}
这是一个二分法寻找数组值的代码,显然这并不是一个好的代码,但是希望它可以说明问题。在面对偶数项时,我选择了靠后的哪项来比较,显然这是一个潜在的危险。但是它不影响我们对对数阶的理解,和上面相比较我们发现,程序不再一一比较,而是通过切分的方法提高了效率,显然这对我们更有益,但是当数组不是升序或者降序的时候我们又应该怎么办呢?(排序算法)
平方阶:平方阶指的是程序重复n的平方次。这在程序中是非常常见的,下面是一个示例。
int times = 0;
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
times++;
}
}
显然,这是一个典型的时间复杂度为平方阶的程序,times最终输出的值为n²。
总结:时间复杂度表示程序最多执行多少次,暗示程序运行时间的长短。执行次数越少,则运行时间更短,反之亦然。
2.2空间复杂度
空间复杂度:表示程序所占用的内存空间的大小。
因为现在目前存储成本较低,所以人们对于空间复杂度的重视程度低于时间复杂度。但是在某些领域,系统的存储空间有限,我们也必须关注这个评价标准。
Ending
总结:下节学习数组