算法
1 数据结构
数据结构 | 存储 | 访问 | 插入删除 |
---|
链表、循环链表、双向链表 | 分散存储、内存空间不连续 | 顺序访问O(n) | O(1) |
数组 | 连续存储 | 随机访问O(1) | O(n) |
栈 | 先进后出FILO(first in last out)、后进先出LIFO(last in first out) | / | / |
队列 | 先进先出FIFO | / | / |
哈希表 | Key+Value | 先通过哈希函数计算哈希值,在取mod(取余)O(1) | O(1) |
堆 | 二叉树存储(父节点必须小于子节点)O(nlogn) | 根节点上总是最小值O(1) | 需要将二叉树重构O(logn) |
二叉查找树(搜索树、排序树) | 二叉树存储(左子节点<根节点<右子节点) | 平衡二叉数O(logn)、单侧纵向延伸O(n) | O(logn) |
图(有向图、无向图) | / | / | / |
2 排序
方法 | 描述 | 速度 |
---|
冒泡排序 | 重复从序列右边开始比较相邻两个数字的大小,根据结果交换两者的位置 |
O
(
n
2
)
O(n^2)
O(n2) |
选择排序 | 从序列中线性查找得最小值,将其与序列最左边的数字进行交换 |
O
(
n
2
)
O(n^2)
O(n2) |
插入排序 | 从右侧未排序的区域内取出一个数据,将它插入到左侧已排序的区域内的合适位置 |
O
(
n
2
)
O(n^2)
O(n2) |
堆排序 | 将数据构件一个堆,不断取出根节点的值,然后使用最后一个节点补充上重新构建 | O(nlogn) |
归并排序 | 将序列不断分成两个长度相同的两个子列,无法继续分时(会形成
l
o
g
2
n
log_2{n}
log2n行),将两个排好序的子序列合并成一个有序数列(归并)(每次比较移动一个数据O(n)),直到成为一个整体 | O(nlogn) |
快速排序 | 从一组数据中随意选一个基准值(pivot),将比它小的放左边,比它大的放右边(平均会分
l
o
g
2
n
log_2{n}
log2n次),每一次分割都要比较n个数据O(n) | O(nlogn) |
3 线性查找
方法 | 描述 | 速度 |
---|
线性查找 | 按顺序查找 | O(n) |
二分查找 | 针对已经排好序的数据进行对半查找 | O(logn) |
4 图搜索
方法 | 描述 | 效率 |
---|
广度优先搜索 | 优先搜索离起点近的候补顶点,先入队的候补顶点先搜索 | 目标离起点越近,搜索越快 |
深度优先搜索 | 沿着一条路径不断往下搜索,直到不能再继续为止,然后再折返(使用栈实现),搜索下一条候补路径 | 与广度优先的不同是选择哪一个候补顶点作为下一个顶点的基准 |
贝尔曼-福特算法 | 寻找图中从起点到终点的路径中权重总和最小的路径,权值可以是负值,能够检测出闭环。从起点开始,选择一条边(无向图双向计算,有向图按方向计算),如果计算值小于顶点值,就更新,并记录父顶点,更新所有的边。重复操作,直到没有权重被更新。 | O(nm),n为顶点数,m为边数 |
Dijkstra算法 | 从起点开始计算候补点到所有点的距离,选择最小的作为候补点,记录父节点,直到搜索到终点。不能应对有负值权重的问题,不能检测闭环。 | 比贝尔曼-福特算法快,比A*慢.
O
(
n
2
)
O(n^2)
O(n2)n为顶点数,m为边数,优化后
O
(
m
+
n
l
o
g
n
)
O(m+nlogn)
O(m+nlogn) |
A*算法 | 从Dijkstra算法中发展来,多了个距离估计值,每一步的结果为权值加估算距离。 | 估计距离值小于实际距离值时,一定可以得出正确答案 |
5 安全算法
存在问题 | 解决方法 |
---|
窃听 | 加密 |
冒充 | 消息认证码or数字签名 |
篡改 | 消息认证码or数字签名 |
事后否认 | 数字签名or数字证书 |
方法 | 描述 | 特点 | 算法 |
---|
加密 | 将有意义的二进制数据转变成无意义的二进制数据(密文),可逆 | / | / |
哈希函数 | 把给定的数据转化成固定长度的无规律数值(十六进制) | 不可逆;1.输出的哈希值数据长度不变;2.如果输入相同的数据,输出的哈希值必定相同;3.即使输入的数据相似,输出的哈希值也有较大的差异;4.输入的数据完全不同,输出的哈希值可能相同(“哈希冲突”);5.不可能从哈希值反向推算出原来的数据;6.求哈希值的运算相对容易 | 哈希算法:MD5(Message digest algorithm),SHA-1(Secure Hash Algorithm),SHA-2(推荐) |
共享密钥加密(对称加密) | 加密和解密都使用相同的密钥。 | 密钥存在被窃听的风险(密钥分配问题),加密解密速度快 | 加密算法:凯撒密码、AES(Advanced Encryption standard)、DES(Data Encryption standard)、动态口令。密钥存在被窃听的风险 |
公开密钥加密 | 加密和解密使用不同的密钥,加密的密钥是“公开密钥”,解密的密钥是“私有密钥”。由接收者生成公钥和私钥,把公钥发送给发出者,发出者将使用公钥加密后的数据发给接收者,接收者使用私钥解密。 | 由于不知道公钥制作人是谁,公钥可能被替换,称为中间人攻击(“man -in-the-middle attack”);加密和解密都比较耗时,不适合连续发送零碎数据 | 加密算法:RAS(三个人名)、椭圆曲线加密 |
混合加密 | 使用速度快的共享密钥对文件进行加密,使用公开密钥对共享密钥进行加密,将二者发送给接收者,接收者使用私有密钥对共享密钥解密,使用解密后的共享密钥对数据进行解密 | 在安全性和速度性上都有优势 | 应用:网络通信安全SSL协议(Secure Sockets Layer, 安全套接层),现更名为TLS协议(Transport Layer Security, 传输层安全) |
迪菲-赫尔曼(Diffie-Hellman)密钥交换 | A将共享密钥发送给B,B使用私有密钥SB合成P-SB,A使用私有密钥SA合成P-SA,AB交换合成后的密钥,将拿到的密钥与私有密钥合成,最终AB手中都是P-SA-SB | 1.密钥之间可以合成,不能分解;2.合成后的密钥还可以继续合成;3.密钥的合成结果与顺序无关,只与使用了哪些密钥有关; | 算法:根据素数P、生成元G和“
G
x
m
o
d
P
G^{x}\ mod\ P
Gx mod P”求出X的问题(离散对数问题,无解) |
消息认证码 | 使用密文和密钥生成的哈希值叫做MAC(Message Authentication Code),如果接收方和发送方的MAC一致,则没有数据篡改 | 无法判断MAC是谁产生的,出现事后否认的问题 | 算法:HMAC(使用广泛)、OMAC、CMAC |
数字签名 | A把数据发送给B,A将数据(或数据的哈希值)使用私有密钥加密得到数字签名,将数字签名发送给B,B使用公有密钥将解密后的数据与A发来的数据对比 | B可以确定数据的发出者是A,但是A可能是X冒充的,因为B收到的公开密钥不知道是A的还是X的,数据也可以是X冒充A发送给B的(这么说,好像数字签名没什么用,A还是不能证明自己是A) | / |
数字证书 | A(使用邮箱和个人公钥)向认证中心(CA,certification Authority)申请数字证书,A将作为公开密钥的数字证书发送给B,B收到后使用认证中心发出的公开密钥验证数字证书 | / | / |
6 聚类
方法 | 描述 |
---|
k-means算法 | 输入多个数据,将相似的数据分为一组。准备好需要聚类的数据,决定族的数量,计算数据点与族点之间的距离,就近分到相应的族中,计算各个族数据的重心,将族中心点移动到这个位置,重复这个过程,直到族中心点不发生变化 |
层次聚类算法 | 一开始数据自成一类,然后与最近的合并成一类,执行n-1次,最终归为1类,根据需求取中间的值 |
7 其他算法
7.1 欧几里得算法(辗转相除法)
- 功能:计算两个数的最大公约数
- 方法:使用二者中的较小数对较大数取余,再用余数对较小数取余,重复这个过程,余为0的时候的较小数就是二者的最大公约数
7.2 素数测试
- 功能:(prime number,只能被1和自身整除的数),判断一个数是素数的概率
- 方法:满足
n
<
p
,
n
p
m
o
d
p
=
n
n<p,n^pmod\ p=n
n<p,npmod p=n的数p可以大概率认为是素数
费马测试:概率性素性测试,判断某个数是素数的概率。任意素数p,
n
<
p
,
n
p
m
o
d
p
=
n
n<p,n^pmod\ p=n
n<p,npmod p=n反之不成立(费马小定理)
卡迈克尔数(Carmichael numbers),绝对伪素数,通过素数测试的非素数,如561,1105…
7.3 网页排名(PageRank, 佩奇排名)
- 功能:在搜索网页时,对搜索结果进行排序
- 方法:计算每个网页的链接权重,链入页面越多的网页,重要性越高;如果出现闭环,使用随机游走模型(random walk model),计算每个网页的权重百分比
7.4 汉诺塔
- 描述:移动圆盘游戏,最小的在上,最大的在下,通过3个栈A,B,C,可以实现从栈A移到栈C
- 效率:
T
(
n
)
=
2
n
−
1
T(n)=2^{n}-1
T(n)=2n−1