数据结构笔记(浙江大学视频课)
第一章
第二节
1.2.1算法的定义
算法
*一个有限指令集
*接受一些输入(有些情况下不需要输入)
*产生输出
*一定在有限的步骤之后终止
*每一条指令必须
*有充分明确的目标,不可以有歧义
*计算机能处理的范围之内
*描述应不依赖于任何一种计算机语言以及具体的实现手段
例1:选择排序算符的伪码描述
void SelectionSort(int List[], int N){
/*将N个整数List[0] ... List[N-1]进行非递减排序*/
for(i=0; i<N; i++){
//从List[i]到List[N-1]中找最小元,并将其位置赋给MinPosition;
MinPosition = ScanForMin(List, i, N-1);
//将未排序部分的最小元换到有序部分的最后位置
Swap(List[i], List[MinPosition]);
}
}
抽象
*List到底是数组还是链表?
*Swap用函数还是宏去实现?
1.2.2什么是好的算法
*空间复杂度
S
(
n
)
S_{(n)}
S(n)
*时间复杂度
T
(
n
)
T_{(n)}
T(n)
例2:
void printN(int N){
if(N){
printN(N-1);
print("%d\n", N);
}
return;
}
printN(100000);//存入存储空间
PrintN(99999);//存入存储空间
PrintN(99998);//…
…
PrintN(0);
S ( N ) = C ⋅ N S(N)=C \cdot N S(N)=C⋅N
例3:
double f(int n, double a[], double x) {
int i;
double p = a[];
for (i = 1; i <= n; i++) {
p += a[i] * pow(x, 1);
}
return p;
}
T ( n ) = C 1 n 2 + C 2 n T(n)=C_1n^2+C_2n T(n)=C1n2+C2n
double f(int n, double a[], double x) {
int i;
double p = a[n];
for (i = n; i > 0; i--) {
p = a[i - 1] + x * p;
}
return p;
}
T ( n ) = C ⋅ n T(n)=C \cdot n T(n)=C⋅n
*在分析一般算法的效率时,我们经常关注下面两种复杂度
*最坏情况复杂度
T
w
o
r
s
t
(
n
)
T_{worst}(n)
Tworst(n)
*平均复杂度
T
a
v
g
(
n
)
T_{avg}(n)
Tavg(n)
T
w
o
r
s
t
(
n
)
<
=
T
a
v
g
(
n
)
T_{worst}(n)<=T_{avg}(n)
Tworst(n)<=Tavg(n)
1.2.3复杂度的渐进表示法
*
T
(
n
)
=
O
(
f
(
n
)
)
T(n)=O(f(n))
T(n)=O(f(n))表示存在常数
C
>
0
,
n
0
>
0
C>0, n_0>0
C>0,n0>0使得当
n
>
=
n
0
n>=n_0
n>=n0时有
T
(
n
)
<
=
C
⋅
f
(
n
)
T(n)<=C \cdot f(n)
T(n)<=C⋅f(n)
若两段算法分别有复杂度
T
1
(
n
)
=
O
(
f
1
(
n
)
)
T_1(n)=O(f_1(n))
T1(n)=O(f1(n))和
T
2
(
n
)
=
O
(
f
2
(
n
)
)
T_2(n)=O(f_2(n))
T2(n)=O(f2(n)),则
*
T
1
(
n
)
+
T
2
(
n
)
=
m
a
x
(
O
(
f
1
(
n
)
,
O
(
f
2
(
n
)
)
)
T_1(n)+T_2(n)=max(O(f_1(n), O(f_2(n)))
T1(n)+T2(n)=max(O(f1(n),O(f2(n)))
*
T
1
(
n
)
×
T
2
(
n
)
=
O
(
f
1
(
n
)
×
f
2
(
n
)
)
T_1(n) \times T_2(n)=O(f_1(n) \times f_2(n))
T1(n)×T2(n)=O(f1(n)×f2(n))
若 T ( n ) T(n) T(n)是关于 n n n的 k k k阶多项式,那么 T ( n ) = O ( n k ) T(n)=O(n^k) T(n)=O(nk)
if-else 结构的复杂度取决于 if 的条件判断复杂度和两个分支的复杂度,总体复杂度取三者中最大