散列
基本概念
- 散列表(hash table哈希表)是一种数据集,其中数据项的存储方式尤其有利于将来快速的查找定位。哈希表中每一个存储位置,称为槽(slot),可以用来保存数据项,每个槽有一个唯一名称.
- 散列函数(hash function):实现从数据项到存储槽名称的转换
- 给定一组数据项,若一个散列函数能将每个数据项映射到不同槽中,则该函数称为“完美散列函数”
- 作为一致性校验的数据“指纹”需要具备:
压缩性 易计算性 抗修改性 抗冲突性
- 散列函数: MD5/SHA
1.MD5(Message Digest):将任意长度的数据变换为固定长位128位(16字节)的“摘要”
2.SHA(Secure Hash Algorithm)## 区块链技术
图片示意:
代码实现:
import hashlib
hash = hashlib.md5()
hash.update(bytes('test',encoding='utf-8'))
print(hash.hexdigest())
区块链技术
基本概念
- 区块链是一种分布式数据库,通过网络连接的节点,每个节点都保存着整个数据库所属有数据,
任何地点存入的数据都会完成同步
数据结构
区块链由一个个区块(block)组成,区块分为(head)和体(body)。
区块头记录了一些元数据和链接到前一个区块的信息(生成时间、前一个区块(head+body)的散列值)
区块体记录了实际数据
散列函数的设计
-
折叠法: 将数据项按照位数分为若干段,再将几段数字相加,最后对散列表大小求余,得到散列值
(有时还有隔数反转步骤,提供了微调手段,以便更好符合散列特性) -
平方取中: 将数据项做平方运算,然后取平方数的中间两位,再对散列表的大小求余
例:对44进行散列
step1: 44*44
step2: 取中 :93
step3: 对列表大小求余(以11为例),93%11=5
-
非数项:将字符串中每个字符看作ASCII码,将码值累加,对列表大小求余
代码实现:
def hash(astring,tablesize):
sum=0
for pos in range(len(astring)):
sum += ord(astring[pos])
return sum%tablesize
冲突解决方案
-
再找一个开放的空槽保存数据项(开放定址Open Addressing)
-
向后逐个槽寻找的方法则是开放定址技术中的线性探测(liner probing)
-
不足:有聚集(clustering)趋势
改进:
- 逐个探测 => 跳跃式探测
-
再散列rehashing
1.还可将线性探测变为“二次探测quadratic probing”
2.不再固定skip的值,而是逐步增加skip值,如1,3,5
3.这样槽号就会是原散列值以平方数增加: h h h, h + 2 0 h+2^{0} h+20, h + 2 1 h+2^{1} h+21… -
数据项链Chaining
将容纳单个数据项的槽扩展为容纳数据项集合(或者对数据项链表的引用)
映射抽象数据类型
-
ADT Map定义操作
Map() 创建空映射,返回空映射对象
put(key,val) 将key-val关联加入映射中,若key已存在,将val替换旧关联值
get(key) 给定key,返回关联值,若不存在,返回空
del 通过del map[key] 形式删除key-val关联
len() 返回映射中key-val关联数目
in key in map 形式,返回key是否在关联中,bool类型
代码实现
class HashTable:
# put方法
def __init__(self):
self.size = 11
self.slots = [None]*self.size
self.data = [None]*self.size
def put(self,key,data):
hashvalue = self.hashfunction(key)
if self.slots[hashvalue] ==None:
self.slots[hashvalue] = key
self.data[hashvalue] = data
else:
if self.slots[hashvalue] == key:
self.data[hashvalue] = data
else:
nextslot = self.rehash(hashvalue)
while self.slots[nextslot] != None and\
self.slots[nextslot]!=key:
nextslot = self.rehash(nextslot)
if self.slots[nextslot] == None:
self.slots[nextslot] = key
self.data[nextslot] = data
else:
self.data[nextslot] = data
def hashfunction(self,key):
return key%self.size
def rehash(self,oldhash):
return (oldhash+1)%self.size
# get方法
def get(self,key):
startslot = self.hashfunction(key)
data = None
stop = False
found = False
position = startslot
while self.slots[position] != None and \
not found and not stop:
if self.slots[position] == key:
found = True
data = self.data[position]
else:
position = self.rehash(position)
if position == startslot:
stop = True
return data
# ADT Map:附加代码
# 通过特殊方法实现[]访问
def __getitem__(self, key):
return self.get(key)
def __setitem__(self, key, value):
self.put(key,data)
未完待续。。。