2

[ 数据结构-C语言 ] 算法的时间复杂度

 2 years ago
source link: https://blog.51cto.com/xingyuli/5262065
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

 目录

1、算法的复杂度

2、时间复杂度​

3、常见时间复杂度计算举例​


1、算法的复杂度

算法在编写成可执行程序后,运行时需要耗费时间资源和空间(内存)资源 。因此衡量一个算法的好坏,一般是从时间和空间两个维度来衡量的,即时间复杂度和空间复杂度。

时间复杂度主要衡量一个算法的运行快慢,而空间复杂度主要衡量一个算法运行所需要的额外空间。在计算机发展的早期,计算机的存储容量很小。所以对空间复杂度很是在乎。但是经过计算机行业的迅速发展,计算机的存储容量已经达到了很高的程度。所以我们如今已经不需要再特别关注一个算法的空间复杂度。(本篇文章主要讨论时间复杂度)

2、时间复杂度

2.1 时间复杂度的定义

时间复杂度的定义:在计算机科学中,算法的时间复杂度是一个函数,它定量描述了该算法的运行时间。一个算法执行所耗费的时间,从理论上说,是不能算出来的,只有你把你的程序放在机器上跑起来,才能知道。但是我们需要每个算法都上机测试吗?是可以都上机测试,但是这很麻烦,所以才有了时间复杂度这个分析方式。一个算法所花费的时间与其中语句的执行次数成正比例,算法中的基本操作的执行次数,为算法的时间复杂度。

请计算一下Func1中++count语句总共执行了多少次?

void Func1(int N)
{
int count = 0;
for (int i = 0; i < N; ++i)
{
for (int j = 0; j < N; ++j)
{
++count;
}
}
for (int k = 0; k < 2 * N; ++k)
{
++count;
}
int M = 10;
while (M--)
{
++count;
}
printf("%d\n", count);
}

时间复杂度函数:F(N)=N*N+2*N+10 

[ 数据结构-C语言 ] 算法的时间复杂度_时间复杂度

 实际中我们计算时间复杂度时,我们其实并不一定要计算精确的执行次数,而只需要大概执行次数,那么这里我们使用大O的渐进表示法。

2.2 大O的渐进表示法

大O符号(Big O notation):是用于描述函数渐进行为的数学符号

1、用1来代替常数,F(N)函数只有常数  O(1)
2、在运行次数中,只保留最高阶。 F(N)=N^3+N^2  --> O(N^3)
3、最高项系数化为1。F(N) = 2*N  --> O(N)

 注:复杂度不固定时,时间复杂度看的是最坏的情况(悲观的估算)

例如:在一个长度为N数组中搜索一个数据x

最好情况:1次找到

最坏情况:N次找到

平均情况:N/2次找到

在实际中一般情况关注的是算法的最坏运行情况,所以数组中搜索数据时间复杂度为O(N)

3、常见时间复杂度计算举例

3.1 冒泡排序的时间复杂度

void BubbleSort(int* a, int n)
{
assert(a);
for (size_t end = n; end > 0; --end)
{
int exchange = 0;
for (size_t i = 1; i < end; ++i)
{
if (a[i - 1] > a[i])
{
Swap(&a[i - 1], &a[i]);
exchange = 1;
}
}
if (exchange == 0)
break;
}
}

[ 数据结构-C语言 ] 算法的时间复杂度_空间复杂度_02

[ 数据结构-C语言 ] 算法的时间复杂度_空间复杂度_03[ 数据结构-C语言 ] 算法的时间复杂度_复杂度_04

 经分析的:F(N)= O(N^2)

3.2 二分查找的时间复杂度

//左闭右开
int BinarySearch(int* a, int n, int x)
{
assert(a);
int begin = 0;
int end = n ;
while (begin < end)
{
int mid = begin + ((end - begin) >> 1);
if (a[mid] < x)
begin = mid + 1;
else if (a[mid] > x)
end = mid;
else
return mid;
}
return -1;
}

//左闭右闭
int BinarySearch(int* a, int n, int x)
{
assert(a);
int begin = 0;
int end = n-1;
while (begin <= end)
{
int mid = begin + ((end - begin) >> 1);
if (a[mid] < x)
begin = mid + 1;
else if (a[mid] > x)
end = mid-1;
else
return mid;
}
return -1;
}

[ 数据结构-C语言 ] 算法的时间复杂度_复杂度_05

假设找了x次:

1*2*2*2*2......*2 = N 

2^x = N

x = log2 N

最坏:O(log2 N)  简写成 log(N)

[ 数据结构-C语言 ] 算法的时间复杂度_复杂度_06[ 数据结构-C语言 ] 算法的时间复杂度_时间复杂度_07

3.3 阶乘(递归)的时间复杂度

1、每次函数调用是O(1),那么就要看他的递归次数。

2、每次函数调用不是O(n),那么就看他的递归调用中次数的累加。

long long Fac(size_t N)
{
if (0 == N)
return 1;
return Fac(N - 1) * N;
}

[ 数据结构-C语言 ] 算法的时间复杂度_空间复杂度_08

[ 数据结构-C语言 ] 算法的时间复杂度_时间复杂度_09[ 数据结构-C语言 ] 算法的时间复杂度_时间复杂度_10

 F(N) = O(N)

3.4菲波那切数列的时间复杂度

long long Fib(size_t N)
{
if (N < 3)
return 1;
return Fib(N - 1) + Fib(N - 2);
}

[ 数据结构-C语言 ] 算法的时间复杂度_复杂度_11

[ 数据结构-C语言 ] 算法的时间复杂度_空间复杂度_12[ 数据结构-C语言 ] 算法的时间复杂度_复杂度_13

[ 数据结构-C语言 ] 算法的时间复杂度_空间复杂度_14[ 数据结构-C语言 ] 算法的时间复杂度_时间复杂度_15 通过计算分析发现基本操作递归了2^N次,时间复杂度为O(2^N)。

(本篇完)


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK