复习:JavaScript中的数组不是数组,底层是由HashTable和链表实现的……
一般翻译做散列、杂凑,是把任意长度的输入(又叫做预映射pre-image)通过散列算法变换成固定长度的输出,该输出就是散列值。
其实是一类算法的总称。只要能够满足任意长度变固定长度,都算是哈希。
Hash算法(函数)通常要求:
如果出现上述第2种情况,我们称其为发生了“碰撞”,越好的散列函数,碰撞应该越少。
常用hash算法包括:MD5(后文详述:Java/C#实现)、SHA-2等,他们都说不可逆的,即无法从输出(散列值)逆推得到输入。
@想一想@:hash算法可以用来干嘛?
哈希表,又称之为散列表。通常用于存放键值对数据(又被称之为字典Dictionary、映射Map等),比如:
学号是键(key),学生是值(value):
学号 |
学生 |
23 |
阿泰 |
14 |
波仔 |
87 |
浪神 |
姓名是键,年龄是值:
姓名 |
年龄 |
阿泰 |
17 |
波仔 |
18 |
浪神 |
23 |
你可能会想象我们用一张专门的表来记录键和地址,然后每一次从上往下遍历这张表找到相应的键值……但等等,只能从上到下遍历么?太慢了,尤其如果键值对的数量比较大的话——干嘛不根据Hash算法通过键直接运算得到值地址呢?!
给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数。
实现上面的目标好像并不难:计算机中任何数据都是二进制,也就是一个数值,我们完全可以像存放数组那样,记录待存储键值对的起始位置,把键转换成数组下标,这样不就OK了么?但是,
为了便于演示,我们用一种最简单的hash算法:除10取余,^_^(@想一想@:这算不算一种Hash算法?)
通过这种哈希算法,我们:
@想一想@:现又要存入一个学号为43的学生,应该如何存放?
43/10=4...3,所以散列值为3,和之前的23碰撞了!惨…… (复习,理解为什么:越好的散列函数,碰撞应该越少)
但如果确实发生了这种情况,只有在3的这个位置,再放一个链表,链表节点中存放上键值对数据……
PS:JavaScript中:
快速比对:Java和C#的对象都可以生成一个哈希值,以快速的比较两个对象的内容是否不同(注意:只能比不同,@想一想@:为什么?)
加密:比如用户注册时的填写的密码,不应该直接(以明文)的方式存储在系统(数据库)中,而是应该对其用MD5加密,这样:
PS:
很多时候,我们还是希望加密了之后能够解密。
比如你想给你的男/女朋友传递小纸条,“今晚8点小树林见”,但不想这纸条的内容被经手的同学知道,你肿么办?
你可以用拼音,拼音还要按某种方式调整顺序,故意加一些无关的混淆符号……
这就是算法,加密算法!
但是,保险不保险?安全不安全?
纯算法加密是有迹可循,可以被破解的,延伸阅读:福尔摩斯 跳舞的小人
为了提高安全性,我们往往在算法的基础上再加一个秘钥:解开加密信息的钥匙。
比如,你收到了一段我发给你的加密信息,按我们约定的加密算法解密之后,发现原文信息是:
01302120070501112080785111066251107
打开飞哥的《折腾》第三卷《从包工头到老码农》这本书:
所以,《从包工头到老码农》这本书就是秘钥。
PS:老谍战片里面所谓的密码本,就这个东西。
按上面的方式,加密解密,用同一把钥匙就可以啦:这就是对称加密。
但非对称加密需要两把钥匙。为了方便,我们称其中一把为公钥,另一把为私钥(只是个称呼,哪一把当公钥哪一把当私钥随便你):
多快好省!前端后端,线上线下,名师精讲
更多了解 加: