1:数据结构
数据结构可以说学习大部分的编程语言都要学习的一门课究竟什么是数据结构呢?
其实数据结构就是指是计算机存储、组织数据的⽅式,指相互之间存在⼀种或多种特定关系的数
据元素的集合。
2:算法
其实算法简单的来说就是
就是定义良好的计算过程,他取⼀个或⼀组的值为输⼊,并产⽣出⼀个或⼀组值作为
输出。简单来说算法就是⼀系列的计算步骤,⽤来将输⼊数据转化成输出结果
3 算法的复杂度:
我们平常在写代码的时候总听见人家说复杂度,代码的效率啊,代码的占用内存啊,听的最多的就是复杂度,负责度也可以分为两种一种就是
空间复杂度和时间复杂度
接下来我讲一一介绍
3.1时间复杂度
时间复杂度主要衡量⼀个算法的运⾏快慢,在计算机发展的早期,计算机的存储容量很⼩。所以对空间复杂度很是在乎。
定义:
在计算机科学中,算法的时间复杂度是⼀个函数式T(N),它定量描述了该算法的运⾏时间。t(n)就是程序执行次数
执⾏次数就可以代表程序时间效率的优劣。⽐如解决⼀个问题的 算法a程序T(N) = N,算法b程序T(N) = N^2,那么算法a的效率⼀定优于算法b
案例:
请计算⼀下
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;
}
}
分析
:
Func1 执⾏的基本操作次数:
T
(
N
) =
N
2
+ 2 ∗
N
+ 10
•
N = 10 T(N) = 130
•
N = 100 T(N) = 10210
•
N = 1000 T(N) = 1002010
通过对N取值分析,对结果影响最⼤
的⼀项是
N
2
实际中我们计算时间复杂度时,计算的也不是程序的精确的执⾏次数,精确执⾏次数来还很
⿇烦的(不同的⼀句程序代码,编译出的指令条数都是不⼀样的),计算出精确的执⾏次数意义⼤,
因为我们计算时间复杂度只是想⽐较算法程序的增⻓量级,也就是当N不断变⼤时T(N)的差别⾯我
们已经看到了当N不断变⼤时常数和低阶项对结果的影响很⼩,所以我们只需要计算程序能代⻓量
级的⼤概执⾏次数,复杂度的表⽰通常使⽤⼤O的渐进表⽰法。
大O的渐进表示法
⼤O符号(Big O notation):是⽤于描述函数渐进⾏为的数学符号
下面一起看推导规则
1.
时间复杂度函数式
T(N)
中,只保留最⾼阶项,去掉那些低阶项,因为当
N
不断变⼤时,
低阶项对结果影响越来越⼩,当
N
⽆穷⼤时,就可以忽略不计了。
2.
如果最⾼阶项存在且不是
1
,则去除这个项⽬的常数系数,因为当
N
不断变⼤,这个系数
对结果影响越来越⼩,当
N
⽆穷⼤时,就可以忽略不计了。
3.
T(N)
中如果没有
N
相关的项⽬,只有常数项,⽤常数
1
取代所有加法常数。
案例:
//
计算
Func2
的时间复杂度?
void Func2(int N)
{
int count = 0;
for (int k = 0; k < 2 * N ; ++ k)
{
++count;
}
int M = 10;
while (M--)
{
++count;
}
printf("%d\n", cou)
解析:
Func2执⾏的基本操作次数:
T
(
N
) = 2
N
+ 10
根据推导规则第3条得出
Func2的时间复杂度为:
O
(
N
)
总结:
通过上⾯我们会发现,有些算法的时间复杂度存在最好、平均和最坏情况。
最坏情况:任意输⼊规模的最⼤运⾏次数(上界)
平均情况:任意输⼊规模的期望运⾏次数
最好情况:任意输⼊规模的最⼩运⾏次数(下界)
⼤O的渐进表⽰法在实际中⼀般情况关注的是算法的上界,也就是最坏运⾏情况
3.2 空间复杂度
空间复杂度也是⼀个数学表达式,是对⼀个算法在运⾏过程中因为算法的需要额外临时开辟的空间。空间复杂度计算规则基本跟实践复杂度类似,也使⽤⼤O渐进表⽰法。
(注意:
函数运⾏时所需要的栈空间(存储参数、局部变量、⼀些寄存器信息等)在编译期间已经确好了,因此空间复杂度主要通过函数在运⾏时候显式申请的额外空间来确定
)
案例:
//
计算
BubbleSort
的时间复杂度?
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;
}
}
解析:
Fac递归调⽤了N次,额外开辟了N个函数栈帧,
每个栈帧使⽤了常数个空间
因此空间复杂度为:
O
(
N)