《数据结构与算法之美》21~25笔记

本文是《数据结构与算法之美》21~25讲的学习笔记,深入探讨了哈希算法在防止用户信息泄露、分布式系统中的应用,如安全加密、唯一标识、数据校验、负载均衡、数据分片等。同时介绍了二叉树的基础,包括二叉查找树的插入、删除和查找操作,讨论了为何在拥有高效散列表的同时仍需要二叉树。此外,文章还提及了红黑树及其在工程中的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文章目录

关于我的仓库

  • 这篇文章是我为面试准备的学习总结中的一篇
  • 我将准备面试中找到的所有学习资料,写的Demo,写的博客都放在了这个仓库里iOS-Engineer-Interview
  • 欢迎star??
  • 其中的博客在简书,CSDN都有发布
  • 博客中提到的相关的代码Demo可以在仓库里相应的文件夹里找到

前言

  • 该系列为学习《数据结构与算法之美》的系列学习笔记
  • 总结规律为一周一更,内容包括其中的重要知识带你,以及课后题的解答
  • 算法的学习学与刷题并进,希望能真正养成解算法题的思维
  • LeetCode刷题仓库:LeetCode-All-In
  • 多说无益,你应该开始打代码了

21讲哈希算法(上):如何防止数据库中的用户信息被脱库

  • 哦,开局就是上古秘辛,2011年CSDN还是用明文保存的账户密码,这也忒靠谱了
  • 幸好那个时候还不知道CSDN是个虾米玩意呢

哈希算法

  • 从哈希值不能反向推导出原始数据(所以哈希算法也叫单向哈希算法)
  • 对输入数据非常敏感,哪怕原始数据只修改了一个Bit,最后得到的哈希值也大不相同
  • 散列冲突的概率要很小,对于不同的原始数据,哈希值相同的概率非常小
  • 哈希算法的执行效率要尽量高效,针对较长的文本,也能快速地计算出哈希值

MD5初识

  • 之前在写网络下载的时候就大概了解过这个算法,这里正好讲到了,我就多查了点资料看了下
  • 首先MD5被称之为不可逆算法,无法从哈希值逆推出原始数据,为什么MD5源码开放的情况下我们会无法逆推呢?因为在哈希过程中,我们不会去刻意保存原数据
  • 比如我们进行了>>操作,将一个二进制数右移了两位,这样子必然会丢失掉最左边的两位,在这样的情况下就算我们有源码知道它进行了右移操作,进行左移,也无法得到原来的那两位,也就无法推倒到原来的数据【这只是一个很简单的例子】
  • 所以对于这样的单向哈希算法,我们在意的只是加密这一过程,因此很多人说MD5不能算加密算法,因为加密会包括加密和解密,而MD5只管杀,不管埋,跟多的是视作一个生成数字签名的算法,从这个角度可能会更好理解这一部分
  • 而我查到的资料提到2004年山东大学一位教授已经破译MD5,是说能够加快碰撞,就是说假如A哈希完结果是B,我现在能找到一个C哈希完也是B,加快了碰撞
  • MD5“解密”过程正确来说不应该叫做“解密”,应该叫做MD5碰撞算法,只是拿到一个原始值再做一次MD5算法,看得到的的MD5值和你之前的MD5是不是一致,如果一致,我们就大体认为是原始值一致。为什么说大体呢?老师也说过了,会有HASH碰撞,可能不一样的原始值长生一样的HASH值,概率为1/2^128

哈希算法七应用【前四】

应用一:安全加密

  • 加密哈希算法举例:MD5(MD5 Message-Digest Algorithm,MD5消息摘要算法)、SHA(Secure Hash Algorithm,安全散列算法)、 DES(Data Encryption Standard,数据加密标准)、AES(Advanced Encryption Standard,高级加密标准)
  • 加密哈希算法的两个特点:
    • 第一点是很难根据哈希值反向推导出原始数据
    • 第二点是散列冲突的概率要很小
  • 首先散列冲突一定会出现,这基于鸽巢原理【如果有10个鸽巢,有11只鸽子,那肯定有1个鸽巢中的鸽子数量多于1个,换句话说就是,肯定有2只鸽子在1个鸽巢内】
  • 而以MD5举例,其哈希值是固定的128位二进制串,最多只有2^128个数据,而我们要哈希的数据是无限的
  • 所有的安全措施,只是增加攻击的成本而已

应用二:唯一标识

  • 这里假如我们要在图库里搜索一张图片是否存在,我们知道所有图片的本质是二进制,如果我们是根据二进制码一个一个对照搜索显然十分耗时【图片大的会有数MB,会很大】
  • 我们可以给每一个图片取一个唯一标识,或者说信息摘要。比如,我们可以从图片的二进制码串开头取100个字节,从中间取100个字节,从最后再取100个字节,然后将这300个字节放到一块,通过哈希算法(比如MD5),得到一个哈希字符串,用它作为图片的唯一标识。通过这个唯一标识来判定图片是否在图库中,这样就可以减少很多工作量
  • 如果还想继续提高效率,我们可以把每个图片的唯一标识,和相应的图片文件在图库中的路径信息,都存储在散列表中。当要查看某个图片是不是在图库中的时候,我们先通过哈希算法对这个图片取唯一标识,然后在散列表中查找是否存在这个唯一标识

应用三:数据校验

  • BT下载的原理是基于P2P协议的。我们从多个机器上并行下载一个2GB的电影,这个电影文件可能会被分割成很多文件块(比如可以分成100块,每块大约20MB)。等所有的文件块都下载完成之后,再组装成一个完整的电影文件就行了
  • 这样就会存在,在某台机器上的资源看你是被恶意修改过的,或者是在下载过程中出现过问题,导致其文件块是不完整的
  • 我们通过哈希算法,对100个文件块分别取哈希值,并且保存在种子文件中。我们在前面讲过,哈希算法有一个特点,对数据很敏感。只要文件块的内容有一丁点儿的改变,最后计算出的哈希值就会完全不同。所以,当文件块下载完成之后,我们可以通过相同的哈希算法,对下载好的文件块逐一求哈希值,然后跟种子文件中保存的哈希值比对。如果不同,说明这个文件块不完整或者被篡改了,需要再重新从其他宿主机器上下载这个文件块
  • 有趣啊,我感觉计算机最有意思的地方就是很多东西完全不是你空想能想到的,想这个数据校验会出现的情况就那么复杂

应用四:散列函数

  • 散列函数是设计一个散列表的关键。它直接决定了散列冲突的概率和散列表的性能。不过,相对哈希算法的其他应用,散列函数对于散列算法冲突的要求要低很多。即便出现个别散列冲突,只要不是过于严重,我们都可以通过开放寻址法或者链表法解决
  • 散列函数对于散列算法计算得到的值,是否能反向解密也并不关心。散列函数中用到的散列算法,更加关注散列后的值是否能平均分布,也就是,一组数据是否能均匀地散列在各个槽中。除此之外,散列函数执行的快慢,也会影响散列表的性能,所以,散列函数用的散列算法一般都比较简单,比较追求效率

解答开篇:守护最好的用户数据库

  • 选择相对安全的加密算法
  • 引入一个盐(salt),跟用户的密码组合在一起,增加密码的复杂度。我们拿组合之后的字符串来做哈希算法加密,将它存储到数据库中,进一步增加破解的难度
  • 现在大多公司都采用无论密码长度多少,计算字符串hash时间都固定或者足够慢的算法如PBKDF2WithHmacSHA1,来降低硬件计算hash速度,减少不同长度字符串计算hash所需时间不一样而泄漏字符串长度信息,进一步减少风险

课后题:现在,区块链是一个很火的领域,它被很多人神秘化,不过其底层的实现原理并不复杂。其中,哈希算法就是它的一个非常重要的理论基础。你能讲一讲区块链使用的是哪种哈希算法吗?是为了解决什么问题而使用的呢?

  • 区块链是一块块区块组成的,每个区块分为两部分:区块头和区块体。
  • 区块头保存着 自己区块体 和 上一个区块头 的哈希值。
  • 因为这种链式关系和哈希值的唯一性,只要区块链上任意一个区块被修改过,后面所有区块保存的哈希值就不对了。
  • 区块链使用的是 SHA256 哈希算法,计算哈希值非常耗时,如果要篡改一个区块,就必须重新计算该区块后面所有的区块的哈希值,短时间内几乎不可能做到。

22讲哈希算法(下):哈希算法在分布式系统中有哪些应用

哈希算法七应用【后三】

  • 个人认为这三点基本上都是一个东西本质上
  • 就是说,怎么追求极致的均衡,方便扩容,缩容
  • 所以思想都一样,注意下应用的场景吧,话说,我觉得这个网课真没白学,是挺有意思的,有一种世界开阔了的感觉

应用五:负载均衡

  • 实现一个会话粘滞(session sticky)的负载均衡算法,我们需要在同一个客户端上,在一次会话中的所有请求都路由到同一个服务器上
  • 我们可以通过哈希算法,对客户端IP地址或者会话ID计算哈希值,将取得的哈希值与服务器列表的大小进行取模运算,最终得到的值就是应该被路由到的服务器编号。 这样,我们就可以把同一个IP过来的所
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值