python实现hash表(上)

#源于数据结构与分析的学习#

字典来实现,字典是储存键(key)-值(value)对的数据类型。键用来查找关联的值,这个常常被称作“映射”

字典的键必须是不可变的,例如字符串、数字或元组等,而值可以是任意类型的对象

对于python中的hash Table 

映射抽象数据类型定义如下。它是将键和值关联起来的无序集合,其中的键是不重复的,键和值之间一一对应的关系。需要映射支持以下操作。让我们来看看。

1.Map()创建一个空的映射,它返回一个空的映射集合。

2.put(key,val)在映射中加入一个新的键值对。如果键已经存在,就用新值替换旧值。

3.get(key)返回key对应的值。如果key不存在,则返回None

4.del通过del map【key】这样的语句从映射中删除键值对。

5.len()返回映射中储存的键值对的数目

6.in通过key in map这样的语句,在键存在时返回True,否则返回False

这是使用字典来实现hash表,其最大优势是,给定一个键,很快就可以找到其关联的值。

但是我们今天用列表来创建一个hash类,实现映射抽象数据类型。

tips:

slots的列表来储存键(key),而data的列表来存储值。两个列表中的键与值在后面一一对应。

那我们先来看看如何定义一个hash类的初始值

class HashTable: #创建一个hash类
    def __init__(self):
       self.size = 11
       self.slots = [None]*self.size
        self.data = [None]*self.size
"""
tips: 1.初始大小可以任意指定,但是选一个素数很关键
在后面的rehash的时候,就不会出现被散列大小整除的现象

2.slots 和 data 用来等效于dic(字典类型)
可以看散列的定义,我们知道初始的时候,每一个槽都是空的
所以这里是设为装有self.size个的[None] 列表

"""

slots 与 data 它们是同步的,到后面我们进行get()和put(),操作的时候就会慢慢的领悟了

上面那句话可以在我们看这些操作时,不断重复,有助于你的理解

“slots的列表来储存键(key),而data的列表来存储值。两个列表中的键与值在后面一一对应。”

好,现在我们来看看其他两大方法

第一个方法:put函数。

但我在此处先写入两个方法,有助于你们的理解

分别是方法1:hashfunction()  和 方法2: rehash()---re有再一次的意义 我们可以理解为 再一次的散列寻找

def function(self,key,size):
    return key%size
#用键(大小)除以散列的长度---结果要求余
#得出的结果,便是该键在散列的初始位置



def rehash(self,oldhash,size)
    return (oldhash + 1)%size
#这个是再散列,目的是解决冲突,散列更加均匀
def put(self,key,data):
    hashvalue = self.hashfunction(key)
#此处求出该数在hash表中的初始位置
    
    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 = rehash(nextslot)
#判断新的节点是否为空或是为对应的键
#直到找到None或是key,才结束循环,然后进行下一步

            if self.slots[nextslot] == None:
                self.slots[nextslot] = key
                self.data[nextslot] = data
            else:
                self.data[nextslot] = data#替换旧值

这便是put方法

接下来我们来看看get方法,它是如何使用双列表来具体实现的

同理,get函数也先计算初始散列值,就是我在上面写的hashfunction()这个方法,用return返回给函数调用端使用,也就是计算机。如果值不在初始散列值对应的槽中,那么我们会使用rehahs()方法来确定下一个位置。

那么我们先来看看这个函数,更好地来解读以下的code。

def get(self,key):
    startslot = self.hashfunction(key) 
#获取该键的初始位置,并将其定为开始位置
    data = None
    stop = False
    found = False
    position = startslot
#接下要使用while循环进行寻找,顺序查找
    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

"""
注意:1.while判断条件这样设置的原因是:1.若寻找时,有位置为空,则该元素不存在
2.若该位置的键相等,说明寻找到了,将该处的data返回给用户
3.为确保循环一定能结束,因为不会回到初始槽,如果
遇到初始槽,则说明已经检查完所有的槽,该元素必定不存在。

"""

为了更好让我们来操作hashTable这个类

我们再附上两个方法,来提供额外的字典功能:

def __getitem__(self,key):
    return self.get(key)
#说明我们可以通过[]来进行访问

def __setitem__(self,key,data):
     return self.put(key,data)

"""
这里我们创建好实例
如:
#1 A = HashTable()
#2 A[54] = "cat" ----已经把这个槽创立好了
#3 print(A[54])
>>> "cat"

以上就是我所的一些操作
"""

还有一部分的方法留到下一期,那么,我们今天对于散列(hashTable)的理解就先到这里

谢谢你的阅读,如有任何疑问,欢迎前来评论区留言

你可能感兴趣的:(哈希算法,算法,python)