我的第一本算法书--读书笔记

序–算法的基本知识

1.什么是算法

计算或解决问题的步骤。

算法和程序的区别

程序是以计算机能够理解的编程语言编写的,算法是以人能够理解的方式描述。

排序

排列整数的算法

选择排序

查找最小的数字并交换

2.算法的计算

2.1用计算机能够理解的方式构思解法

计算机能够高速执行基本命令,但无法执行复杂的命令。
如何处理复杂的操作:通过搭配组合基本命令来应对。
设计算法就是构思如何搭配组合计算机可以执行的那些基本命令来实现这个操作。

3.算法的选择

主要关注的是算法的运行时间,即从输入数据到输出结果这个过程所花费的时间。

4.运行时间的计算方法

4.1输入数据的量和运行时间之间的关系

输入数据量的大小不同,运行时间也不同。

4.2如何求得算法的运行时间

采用步数来描述运行时间,1步就是计算机运行时间的基本单位。
通过测试计算从开始到结束总共执行了多少步来求得。

5.运行时间的表示方法

时间复杂度:是一个描述算法运行时间的函数,用大O符号来表述。O的意思是忽略重要项以外的内容。

第一章 数据结构

1-1什么是数据结构

概念:决定数据顺序和位置关系的规则。
作用:选择合适的数据结构以提高内存的利用率。

1-1-1链表

定义:数据呈线性存储,每个数据都有一个指针,指向下一个数据的内存地址。
特点:
	添加和删除:增删快,添加、删除只需要改变位置前后的指针就可以。
		时间复杂度:O(1)
	查询:查询慢,查询需要从头遍历。
		时间复杂度:O(n)
内存:数据一般是分散于内存中,无需存储在连续空间中。
访问顺序:顺序存储。
1-1-1-1循环链表
概念:在链表尾部使用指针,并让它指向链表头部的数据,将链表变成环形。
使用场景:保存数量固定的最新数据。
1-1-1-3双向链表
概念:除了第一个数据和最后一个数据外,每个数据都有两个指针,分别指向前后数据。
优点:不仅可以从前往后遍历,还可以从后往前遍历。
缺点:指针会导致存储空间需求增加;添加和删除时需要改变更多指针的指向。

1-1-2数组

定义:数据呈线性排列,并按顺序存储在内存的连续空间内。
特点:
	查找快:由于数据是存储在连续空间内,所以每个数据的内存地址都可以通过下标算出,就可以进行随机访问(通过下标访问目标数据)。
	增删慢:想在任意位置上添加或删除数据,需要移动数据。
时间复杂度:
	查找:O(1)
	增删:O(n)

1-1-3栈

定义:数据呈线性排列,添加和删除数据只能在一端进行,访问数据只能访问顶端的数据。
概念:
	入栈:添加数据。
	出栈:取出数据。
特点:后进先出。
应用场景:只需要访问最新数据的情况。

1-1-4队列

定义:数据呈线性排列,添加和删除操作分别在两端进行。
概念:
	入队:添加数据。
	出队:删除(取出)数据。
特点:先进先出。

1-1-5哈希表

定义:哈希表存储的是由键和值组成的数据。
原理:
	链地址法:在存储数据之前,对数据进行hash计算得到一个hash值,然后进行取模计算,结果计算出一个地址,将数据放进去,如果出现冲突则使用						链表存储。
	开发地址法:当冲突发生时,立刻计算出一个候补地址并将数据存进去,如果仍有冲突,便继续计算下一个候补地址,直到有空地址为止。可以通过多						次使用哈希函数或线性探测法等方法计算候补地址。
查询:当要查询某个数据时,先对键进行哈数计算,再对其取模计算,根据结果到对应位置查看,如果是链表就进行线性查找。

1-1-6堆

定义:一种图的树形结构,被用于实现优先队列,可以自由添加数据,但取出数据时要从最小值开始按顺序取出。
特点:堆中的每个结点最多有两个子结点,树的形状取决于数据的个数。子结点必定大于父结点。
时间复杂度:
	取出最小值:O(1)
	重构树:O(logn)
	添加数据:O(logn)
应用场景:需要频繁地从管理的数据中取出最小值。

1-1-7二叉树

定义:采用了图的树形结构,数据存储于二叉查找树的各个结点中。
特点:每个结点最多有个两个子结点。
性质:
	1.每个结点的值均大于其左子树上任意一个结点的值。
	2.每个结点的值均小于其右子树上任意一个结点的值。
	3.二叉查找树的最小结点要从顶端开始,往其左下的末端寻找。
添加结点:
	1.从顶端开始寻找添加数字的位置。
	2,将想要添加的结点与该结点中的值进行比较,小于它则往左移,大于它则往右移。
删除结点:
	1.如果要删除的结点没有子结点,直接删除。
	2.如果要删除的结点只有一个子结点,那么先删除目标结点,然后把子结点移到被删除结点的位置上。
	3.如果需要删除的结点有两个子结点,那么先删除目标结点,然后在被删除结点的左子树中寻找最大结点,将最大结点移到被删除结点的位置上。
时间复杂度:添加和查询:
							树的形状均衡:O(logn)
							树的形状不均衡:
扩展:
	平衡二叉树:数据结构可以修正形状不平衡的树,让其始终保持均衡状态,以提高查询效率。
	B树:子结点可以自由设定,并且形状均衡。

第二章 排序

2.1什么是排序

排序就是将输入的数字按照从小到大或从大到小的顺序进行排列。

2.2冒泡排序

定义:重复“从序列右边开始比较相邻两个数字的大小,再根据结果交换两个数字的位置”这一操作的算法。
时间复杂度:O(n^2)

2.3选择排序

定义:重复“从待排序的数据中寻找最小值,将其与序列最左边的数字进行交换”这一操作的算法。属于线性查找。
时间复杂度:O(n^2)

2.4插入排序

定义:从序列左端开始依次对数据进行排序的算法。思路就是从右侧的未排序区域内取出一个数据,然后将它插入到已排序区域内合适的位置上。
时间复杂度:O(n^2)

2.5堆排序

特点:利用了堆,将所有数据都放入堆中,并按降序来构建。从堆中取出数据时会从最大的数据开始取,所以将取出的数据反序输出,排序就完成了。
时间复杂度:O(nlogn)

2.6归并排序

特点:把序列分成长度相同的两个子序列,当无法继续往下分时(也就是每个子序列中只有一个数据时),就对子序列进行归并,即把两个排好序的子序列		合并成一个有序序列。
时间复杂度:O(nlogn)

2.7快速排序

特点:首先会在序列中随机选择一个基准值,然后将除了基准值以外的数分为“比基准值小的数”和“比基准值大的数”这两个类别,再将其排列成一下形		式。[比基准值小的数]基准值[比基准值大的数],接着,对两个“[]”中的数据进行排列之后,整体的排序便完成了。
时间复杂度:O(nlogn)
分治法:将原本的问题分成两个子问题,然后在分别解决这两个问题。
递归:在算法内部继续使用该算法的现象被称为“递归”。

第三章 数组的查找

3.1线性查找

概念:在数组中从头开始依次往下查找。
简述:是一种在数组中查找数据的算法。
时间复杂度:O(n)
适用场景:在数组中添加数据时无需考虑位置,直接把它加在末尾即可,不需要耗费时间。

3.2二分查找

概念:查找已经排好序的数据,通过比较数组中间的数据与目标数据的大小,可以得知目标数据时在数组的左边还是右边,以此缩小范围,重复执行该操			作就可以找到目标数据,或得出目标数据不存在的结论。
时间复杂度:O(logn)
适用场景:在数组中查找时。

第四章 图的搜索

4.1 图的搜索

概念:
	图:由顶点和连接每对顶点的边所构成的图形就是图。
	图的搜索:从图的某一个顶点开始,通过边到达不同的顶点,最终找到目标顶点的过程。
作用:可以表现各种关系。
图的分类:
	加权图:给边加上一个值,这个值叫权重,加了权重的图叫加权图,它可以表示顶点之间的连接程度。
	有向图:给边加上箭头,这样的图就叫有向图。
	闭环图
	非闭环图:树
应用场景:寻找计算机网络中通信时间最短的路径,寻找路线图中耗时最短的路径,寻找路线图中最省乘车费的路径。
分类:
	广度优先搜索
		概念:一种对图进行搜索的算法,从起点开始顺着边搜索,直到到达指定顶点,再此过程中每走到一个顶点,就会判断一次它是否为终点。从离起点					近的顶点开始搜索。
		过程:从顶点出发,下一次的所有结点称为候补结点,在同层候补结点里随机选择一个结点作为下一个结点,它的下一层的所有结点称为候补结点,					接着最早成为候补结点的结点依次进行遍历,重复上述操作直到到达指定的顶点。
		特点:目标顶点离起点越近,搜索结束得就越快。
	深度优先搜索
		目的:从起点开始搜索直到到达指定顶点。
		特点:沿着一条路径不断往下搜索直到不能再继续为止,然后再折返,开始搜索下一条候补路径。
		数据结构:后入先出,使用栈来实现。
基本问题:最短路径问题————在从s到t的路径中,找到一条所经过的边的权重总和最小的路径。

4.2 贝尔曼-福特算法

概念:一种在图中求解最短路径问题的算法。
最短路径问题:在加权图指定了起点和终点的前提下,寻找从起点到终点的路径中权重总和最小的那条路径。
过程:
	1.首先设置各个顶点的初始权重,起点为0,其他顶点为无穷大,该权重表示从A到到该顶点的最短路径的暂定距离。
	2.选出一条边,分别计算这条边从一端到另一端的权重,即“顶点原本的权重+边的权重”。
	3.如果计算结果小于顶点的值,就更新这个值。更新时需要计算式从哪个顶点到该顶点的路径。
	4.对所有的边都进行同样的操作。
	5.重复对所有边的更新操作,直到权重不能被更新为止。
	6.选择最短的路径。
时间复杂度:O(nm)

4.3 狄克斯特拉算法

目的:求解最短路径问题,求得从起点到终点的路径中权重总和最小的那条路径。
过程:从开始顶点初步计算每个顶点的权重,并选择最短权重的顶点,直到到达终点。
时间复杂度:
	未优化:O(n^2)
	优化:O(m+nlogn)
问题:含有负数权重时,该算法可能无法得到正确答案,因此有负数权重时不能使用狄克斯特拉算法。

4.4 A*算法

目的:求解最短路径。
优点:预先估计一个值,利用这个值省去一些无用的计算,基本不会计算太远的区域。
求解过程:
	1.在图中设置起点和终点。
	2.给每个顶点设置一个终点的距离估算值。
	3.分别计算起点周围每个顶点的权重,即从起点到该顶点的距离加上估算值。
	4.选择一个权重最小的顶点,设为搜索完毕后计算下一个顶点的权重。
	5.选择距离短的顶点,重复步骤直到到达终点。
适用场景:直到各个顶点到终点的大致距离就能使用该算法,距离估算值越接近当前顶点到终点的实际值,该算法就越高效。
真是应用:游戏编程中用于计算敌人追赶玩家时的行动路线,由于计算量大会导致游戏运行速度慢,一般结合其他算法考虑。

第五章 安全算法

5.1 安全技术的意义

数据在传输过程中可能会经过某些恶意用户的设备,从而导致内容被盗取。

5.2 传输数据时的四个问题

窃听:A向B发送的消息可能在传输图中被X偷看。
假冒:A向B发送消息,A或B可能是X冒充的。
篡改:B确实收到了A发送的消息,但内容可能在途中被X更改了。
事后否认:B收到了A发送的消息,但A可能对B抱有恶意,并在事后否认给B发送消息。

5.3 问题解决方案

窃听:加密技术。
假冒:消息认证码或数字签名。
篡改:消息认证码或数字签名。
事后否认:
	数字签名
		--问题:无法确认公开密钥的制作者。
		--解决:使用数字证书技术。

5.4 加密

密文:加密后的数据。
加密:数据经过某种运算后,变成计算机无法理解的数据的过程;即用密钥对数据进行数值运算,把数据变成第三者无法理解的形式的过程。
解密:通过密钥进行数值计算,把密文恢复成原本数据的过程。
加密技术:加密和解密的过程。

5.4.1 加密方法

5.4.1.1 共享密钥加密(对称加密)
概念:加密和解密都使用相同的密钥。
实现:凯撒密码、AES、DES、动态口令。
问题:
	密钥分配问题:密文和密钥都可能会被窃听,密钥被窃听后,窃听者就能解密了。
5.4.1.2 公共密钥加密(非对称加密)
概念:加密和解密使用不同密钥的一种加密方法。
	公开密钥:加密用的密钥。
	私有密钥:解密用的密钥。
实现:RAS算法、椭圆曲线加密算法。
	条件:
		1.可以使用某个数值对数据进行加密。
		2.使用另一个数值对加密数据进行计算就可以让数据恢复原样。
		3.无法从一种密钥推算出另一个密钥。
过程:
	1.有接收方B来生成公开密钥和私有密钥。
	2.把公开密钥发送给A,A使用公开密钥加密数据。
	3.A将密文发送给B,B使用私有密钥对密文进行解密。
问题:
	可靠性问题:
		介绍:A无法判断收到的公开密钥是否来自于B
		过程:在接收方B给A发送公开密钥的过程中有可能被X窃听并把B的公开密钥替换成自己的,然后发送给A,A解密后发送密文,被X窃取,然后使用B				 的公共密钥加密后传给B,整个过程无人发现,即中间人攻击。
		解决:数字证书。
	性能:加密和解密比较耗时,不适用于持续发送零碎数据。
		解决:使用混合加密解决。
5.4.1.3 混合加密
概念:用共享密钥加密对数据进行加密,加密时使用的密钥,需要用公开密钥加密进行加密。
过程:
	1.A准备通过互联网向B发送数据。
	2.A使用共享密钥加密对数据进行加密。
	3.B事先生成公开密钥和私有密钥,将公开密钥发给A,A使用公开密钥对共享密钥的密钥进行加密,再发送给B。
	4.B接收到密文后使用私有密钥解密。
	5.A使用共享密钥对数据加密并发送给B。
应用:SSL协议
5.4.1.4 迪菲-赫尔曼密钥交换/协议
概念:是一种可以在通信双方之间安全交换密钥的方法,通过将双方共有的秘密数值隐藏在公共数值相关的运算中,来实现双方之间的密钥安全交换。
过程:
	1.用P、G两个整数来表示一个开始生成的公开密钥P,其中P是一个非常大的素数,而G是P对应的生成元中的一个。
	2.由A准备P和G,并将他们发送给B。
	3.A和B分别准备各自的秘密数字X和Y,都必须小于P-2,分别计算G^x mod P和G^y mod P,该运算等同于合成。
	4.A、B将自己的计算结果发送给对方。
	5.A、B收到后,先计算这个值的次方,再mod P,最后A和B得到相同的结果。
	6.即便X窃听了整个通信过程,也无法窃听到计算出的A和B共有的数字。
原理:利用了“离散对数问题”这个数学难题。
5.4.1.5 消息认证码
概念:可以实现“认证”和“检测篡改”,密文内容在传输过程中可能会被篡改,导致解密后内容发生变化,从而产生误会。
过程:
	1.A从B处购买商品,需要将商品编号abc告诉B。
	2.A使用共享密钥加密对消息进行加密,然后通过安全的方法将密钥发送给了B。
	3.A使用双方共有的密钥对消息进行加密。
	4.A把密文发送给B,B收到后对密文进行解密,最终得到原本的商品编号abc;假设在此过程中消息被X更改,B对被篡改的密文进行解密,得到消息				xyz,B会将错误的商品发送给A。
	4.(改)在发送密文的同时,A生成一个用于制作消息认证码的密钥,然后使用安全的方法将密钥发送给B。
	5.A使用密文和密钥生成一个值,即消息认证码MAC,并将MAC发送给B。
		MAC:密钥和密文组成的字符串的哈希值,计算MAC算法有HMAC、OMAC、CMAC等,HMAC应用最为广泛。
	6.B也使用密文和密钥生成MAC,经过对比判断,B可以确认自己计算出来的是否和A计算出来的一致。
	7.如果A发送的密文被篡改,B通过MAC计算发现不一致,则会放弃密文和MAC,向A提出再次发送的请求。
问题:使用MAC时不能确定MAC由哪方生成。
5.4.1.6 数字签名
概念:不仅可以实现消息认证和检测篡改功能,还可以预防事后否认问题,数字签名只有发信人才能生成,因此使用它就可以确定谁是消息的发送者了。
使用过程:
	1.A向B发送消息之前给消息加上数字签名。
	2.B收到消息后,可以确认数字签名确实是由A生成的,B可以验证数字签名的正确性,但无法生成数字签名。
生成过程:
	1.由消息的发送者发送给B。
	2.A将公开密钥发送给B,A使用私有密钥加密消息(先求得消息的哈希值,再对哈希值进行加密)。加密后的消息就是数字签名。
	3.A将消息和签名都发送给B。
	4.B使用公开密钥对签字进行解密,并比对是否和收到的消息一致。
	5.RSA加密算法可以实现。
问题:无法确定公开密钥的制作者是谁,公开密钥有可能是由某个冒充A的人生成的。
5.4.1.7 数字证书
作用:保证公开密钥的正确性。
过程:
	1.A持有公开密钥PA和私有密钥SA,现在想要将公开密钥PA发送给B。
	2.A首先需要用自己的邮箱地址向认证中心CA申请发行证书,证明公开密钥确实是自己生成。
	3.认证中心保管着他们准备的公开密钥PC和私有密钥SC。
	4.A将公开密钥PA和包含邮箱信息的个人资料发送给认证中心。
	5.认证中心根据资料判断是否为A本人的资料,确认完毕后,认证中心使用自己的私有密钥SC,根据A的资料生成数字签名。
	6.认证中心将生成数字签名和资料放进同一个文件中,然后把这个文件发送给A,这个文件就是A的数字证书。
	7.A将作为公开密钥的数字证书发送给B。
	8.B收到数字证书后,确认证书里的邮箱地址确实是A的地址,然后B获取了认证中心的公开密钥。
	9.B通过PC对数字证书进行验证,如果结果没有异常,就能说明这份证书的确由认证中心发行。
	10.从证书中取出Ad公开密钥PA。
问题:存在认证中心被冒充的情况
	解决:实际上,更高级别的认证中心对这个认证中心发行证书,最顶端的认证中心被称为“根认证中心”,其自身的正当性由自己证明,即使用根证书;				如果根认证中心不被信任,整个组织就无法运转,根认证中心大多为大型企业,或与政府关联且已经取得了社会信赖的组织。
规范:公钥基础设施PKI
5.4.1.8 哈希函数
作用:把给定的数据转换为固定长度的无规律数值(通常用十六进制来表示)。
特征:
	1.输出的哈希值数据长度不变。
	2.如果输入的数据相同,那么输出的哈希值也必定相同。
	3.即使输入的数据相似,输出的哈希值也会有很大差异。
	4.即使输入的两个数据完全不同,输出的哈希值也有可能相同,这种情况叫作“哈希冲突”。
	5.不可能从哈希值反向推算出原本的数据。
应用:实现基于密码的用户认证--将用户输入的密码保存到服务器;当用户输入密码时,先算出该输入密码的哈希值,再把它和服务器的哈希值进行对			比,即使哈希值暴露了,第三者也无法得知原本的密码。

第六章 聚类

6.1 概念

在输入为多个数据时,将相似的数据分为一组的操作,一个组就叫一个簇。

6.2 定义相似

如何定义相似就是定义数据间的差距。

6.3 算法

6.3.1 k-means算法

概念:可以根据事先准备好需要聚类的数据,然后决定簇的数量。
过程:
	1.首先准备好需要聚类的数据,然后决定簇的数量。
  2.随机为每个簇选择一个中心点。
  3.计算各个数据分别和各个中心点中的哪一个点距离最近。
  4.将数据分到相应的簇中。这时聚类就完成了。
  5.计算各个簇中数据的重心,然后将簇的中心点移动到这个位置。
  6.重新计算距离最近的簇的中心点,并将数据分到相应的簇中。
  7.重复执行“将数据分到相应的簇中”和“将中心点移到重心的位置”这两个操作,直到中心点不再发生变化为止。
总结:随着操作的不断重复,中心点的位置必定会早某处收敛。

6.3.2 层次聚类算法

概述:一开始每一个数据都自成一类,然后重复执行“将距离最近的两个簇合并为一个”的操作,最后所有数据都被分到一个簇中。在这个过程中,每个阶		段的簇的数量都不同,对应的簇类结果也不同。只要选择其中最为合理的一个结果就好。
找出“距离最近的两个簇”的算法:最短距离法、最长距离法、中间距离法。

第七章 其他算法

7.1 欧几里得算法

概念:用于高效计算两个数的最大公约数。
优势:即使两个数字再大,只要按照步骤进行操作就能高效地求出两者的最大公约数。
步骤:
	1.首先用较小的数字去除较大的数字,求出余数。即对两个数字进行mod运算。
	2.接下来用上一步的除数和余数进行mod运算
	3.继续重复同样的操作,直到结果为0,即最后一步的除数可以被余数整除,那么最后一次计算中的除数就是最大公约数。
原理:将两个数分成几等分,一份就是最大公约数,通过mod的运算将两个数的分数减少,直到只有一份,即是最大公约数。

7.2 素性测试

概念:判断一个自然数是否为素数的测试。素数就是只能被1和其自身整除,且大于1的自然数。
应用:加密算法RSA会用到大素数。

7.2.1 应用

目的:判断某个数是素数的概率大不大。
概念:根据是否满足费马小定理来判断一个数是否为素数的方法就是费马测试。
费马小定理:p=素数,n<p,n^p mod p=n。
应用:确认n和余数一致的次数越多,确定为素数的可能性就越大,如果确认了几组n和余数之后就能判断该数是素数的可能性非常高,那么大致就可以判		定为该数是是素数了。
扩展:
	米勒-拉宾素数测试:
		根据费马测试改进而来,当数不是素数的概率小于0.5的80次方时,就可以大致判断该数为素数。

7.3 网页排名(佩奇排名)

概念:一种在搜索网页时利用网页之间的链接结构计算出网页价值并对搜索结果进行排序的算法。
排序规则:按照页面的重要性排序,链入页面越多的网页,重要性越高。
思路:
	1.没有链入页面的网页权重为1
	2.有链入页面的网页权重是其链入页面的权重之和
	3.如果一个网页链向多个页面,那么其链向的所有页面将平分它的权重
	4.如果出现环状的链接结构使用随机游走模型直接将浏览网页的概率作为网页的权重来使用。

7.4 汉诺塔

递归算法的应用:在算法描述中调用算法自身的方法叫作“递归”。
运行时间:T(n)=2^n-1
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值