一个算法的优劣好坏,会决定一个程序运行的时间、空间。也许当小数据量的时候,这种影响并不明显,但是当有巨量数据的时候,算法的好坏带来的性能差异就会出天差地别。可以说直接影响了一个产品的高度和广度。每个程序员都想用最优的算法解决问题,我们期待自己写出的代码是简洁、高效的。但是如何评判一个算法的好坏呢?时间复杂度和空间复杂度就是一个很好的标准。
执行算法所需要的计算工作量就是我们常说的时间复杂度。该值不一定等于接下来要介绍的基本执行次数。是一个大约的数值,具有统计意义。
根据计算,得出的该算法在输入数据量为n时的,实际执行次数。该值为准确的,具体的数值,有数学意义。
根据基本执行次数,去除系数、常数项等得到的渐进时间复杂度。用大O表示法。也就是说,随着数据量的剧增,不同常数项和系数,已经大致不能够影响该算法的基本执行次数。常数项和系数对于计算时间复杂度无意义
void test(int n)
{
int a;
a = 10;
}
void test(int n)
{
int cnt;
for (cnt = 0; cnt < n; cnt++) {
int a;
a= 10;
}
}
void test(int n)
{
int cnt1, cnt2;
for (cnt1 = 0; cnt1 < n; cnt1++) {
for (cnt2 = cnt1; cnt2 < n; cnt2++) {
int a;
a = 10;
}
}
a = 11;
}
void test(int n)
{
int cnt;
for (cnt = 1; cnt < n; cnt *= 2) {
int a;
a = 10;
}
}
void test(int n)
{
int cnt1, cnt2;
for (cnt1 = 0; cnt1 < n; cnt1++) {
for (cnt2 = 1; cnt2 < n; cnt2 *= 2) {
int a;
a = 10;
}
}
}
void test(int n)
{
int cnt1, cnt2, cnt3;
for (cnt1 = 0; cnt1 < n; cnt1++) {
for (cnt2 = 0; cnt2 < n; cnt2++) {
for (cnt3 = 0; cnt3 < n; cnt3++) {
int a;
a = 10;
}
}
}
}
int test(int n)
{
if (n == 0 || n == 1) {
return 1;
}
return (test(n-1) + test(n-2));
}
O(1) < O(log2n) < O(n) < O(nlog2n) < O(n^2) < O(n^3) < O(2^n) < O(n!) < O(n^n)
一个算法所占用的存储空间主要包括:
输入数据所占空间只取决于问题本身,和算法无关。我们所说的空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度,即第三项。通常来说,只要算法不涉及到动态分配的空间以及递归、栈所需的空间,空间复杂度通常为0(1)。
int test(int n)
{
int a, b, c;
int cnt;
for (cnt = 0; cnt < n; cnt++) {
a += cnt;
b += a;
c += b;
}
}
int test(int n)
{
int a = 1;
if (n == 0) {
return 1;
}
n -= a;
return test(n);
}
在上面的例子中,我们通常都会舍弃掉系数和常数项。这是因为当输入量剧增,接近正无穷时,系数和常数项已经不能够影响执行次数曲线。不同的系数和常数项曲线会完全重合。我做了一个折线图用来比较当输入值n激增时,n^2 曲线和 2n^2 + 100 曲线。可以看到,当数据量剧增时,系数和常数项对于统计时间复杂度都不再有意义,两条曲线几乎完全重合。
下图是我做的一个表格,整理了不同的排序算法的时间复杂度和空间复杂度供大家参考:
敬告:
本文原创,欢迎大家学习转载
转载请在显著位置注明:
博主ID:CrazyCatJack
原始博文链接地址:https://www.cnblogs.com/CrazyCatJack/p/12657097.html
原文:https://www.cnblogs.com/CrazyCatJack/p/12657097.html