如何在Python中实现HashMaps

64 阅读6分钟

每当我们试图通过我们的数据实现某种搜索逻辑时,我们希望它是 高效.在小程序中可能不是这样,但对于拥有庞大代码库的大型应用程序,运行任何一种逻辑的搜索、删除或修改时间都应该是最小的。

Python中的字典是用来存储数据的,即Key:值对。它们使用一种叫做Hashing的技术来执行基于时间的搜索操作,这几乎与字典的大小无关**。**

什么是Hashing?

散列是一种用来对任何类型的数据进行排序和索引的技术。散列允许我们对大量的数据或输入进行索引,并将它们存储在较小的输出空间中,所使用的键一般是用一种叫做散列函数的东西来创建的,它本质上是某种应用于我们的输入数据的数学逻辑,从而得到一个数值。

哈希的概念

让我们假设我们有三个字符串,我们想用某种数学逻辑以一种有效的方式来存储它们。这里我们有约翰、彼得卡莉三个字符串。因此,如果你想用散列法来存储它们,这里的第一步是我们用一些散列函数将这些字符串变成一个数字。

如果我们使用散列函数将这些字符串转换为数字,我们首先将约翰字转换为10,然后我们将彼得转换。它被转换为5。然后我们在继续转换Carrie,这将是11。因此,我们已经将我们的字符串转换成了数字。

现在你可能会感兴趣,如何转换,这里的 Hash函数是什么,它是如何工作的。我们将在文章中进一步了解这个问题。

Python中的哈希函数

哈希函数负责通过使用一些公式将这些字符串转换为数字。

接下来,我们必须将这些数字存储在一些数据结构中。如果我们有一个数组或python列表,其中有12个单元,如图所示,通过使用这个哈希函数生成的数字,我们将把这些字符串插入这些数组中。

所以对于第一个字符串,也就是约翰,我们有10个。我们将John 字符串插入到 10的索引在这个数组中。然后,下一个字符串是彼得。所以当我们把它转换成数字时,它就变成了5。

我们将插入Peter字符串到 5的索引.现在,下一个词是Carrie。当我们通过使用这里的哈希函数转换Carrie时,它就变成了11。所以我们将把Carrie插入到 11的索引到这边的这个数组中。我们已经完成了这些字符串到整数的转换,我们正在将这些字符串插入这个数组中。

使用哈希函数读取或访问数据

现在,问题是,如果我们想从这里的数组中读取数据,我们如何访问它?

同样,逻辑也是一样的。例如,如果我们想访问约翰,我们要做的第一件事就是使用同样的哈希函数,将约翰转换成数字。每次我们转换相同的字符串时,结果都是一样的。所以我们会得到10。基于10的索引,我们可以访问这边的这个元素。

为什么我们需要Hashing?

我们知道,根据索引访问数组或 Python 列表中的一个元素需要 ***O(1)***时间复杂度.这就是为什么在数据结构中搜索一个给定的值时,散列是非常重要的。通过这样做,我们可以很容易地确定这个字符串是否在这个数组中。

假设我们想开发一个应用程序,其中大量使用搜索操作,我们希望我们的应用程序尽可能快地执行。在这种情况下,我们可以使用散列。在搜索操作方面,散列也比其他数据结构表现得更好。

散列术语

  • 哈希函数:它是一种逻辑或数学公式,可用于将任意大小的输入数据映射到固定或较小大小的输出。
  • 哈希值:它是由哈希函数返回的值。
  • 哈希表:它是实现关联数组抽象数据类型的数据结构,也是可以将键映射到值的结构。
  • 碰撞:当一个哈希函数的两个不同的键产生相同的输出时,就会发生碰撞。

在 Python 中实现 HashMap

让我们试着通过实现一个哈希图来了解它的概况。我们将创建一个包含基本函数的自定义类。下面是包含在我们的自定义类中的函数。代码本身包含了我们之前在文章中讨论的所有解释。

  • _hash(self,key)这是我们定义的哈希函数或数学逻辑,我们将其应用于密钥,将其转换为一个积分值。
  • set*(self,key,value)这个函数将允许我们向我们的哈希图添加一个键|值对。
  • get(self,key):要为给定的键检索一个值,可以利用这个函数。
  • __str__(self)将完整的哈希图输出到我们的终端。
代码
class HashMap(object):
    def __init__(self, size):
        """Initializing the list with the argument size for our HashMap"""
        self.data = [[]] * (size)

    def _hash(self, key):
        """Hash Function:
        marked as a private method in the Object"""

        # Initialize
        hash_value = 0

        # Iterating and generating hashed values using the logic below
        # Logic: Taking the initial value of 0 and adding to it the ASCII encoding for each character,
        # and multiplying by the index value. After that we are taking the modulus of the result using the
        # length of the array
        # This becomes our hashed value i.e. the index position of the input to be placed
        # in the output space
        for i in range(len(key)):
            hash_value = (hash_value + ord(key[i]) * i) % len(self.data)

        return hash_value

    def set(self, key, value):
        # Represents the index position where we want to store our data
        address = self._hash(key)

        if not self.data[address]:
            self.data[address] = []
        # If there is a collision of index value i.e. our hashed value
        # then simply add on to that array
        self.data[address].append([key, value])
        return self.data

    def get(self, key):
        # Getting the hashed value again, with the same hash function to locate the value
        # for the given key
        address = self._hash(key)
        # assigning the entire array to a variable in-order to operate later
        currentBucket = self.data[address]

        if currentBucket:
            # Iterating over the entire list to get the value
            for i in range(len(currentBucket)):
                # Check to retrieve the value
                if currentBucket[i][0] == key:
                    # If found, return the current bucket
                    return currentBucket[i][1]

        # If no value present
        return "Data Not Found"

    # In order to print the hashmap to see the structure
    def __str__(self):
        return "".join(str(item) for item in self.data)


# Instantiating from our Object Class with 50 buckets
myHash = HashMap(50)

# Setting the values to the hash table
myHash.set("john", 123)
myHash.set("peter", 567)
myHash.set("carrie", 898)

# Printing the entire hash table
print(myHash)

# Getting the values from the hash table using the keys
print(myHash.get("john"))  # Output: 123
print(myHash.get("guava"))  # Output: Data Not Found

总结

在这篇文章中,我们介绍了使用Python创建哈希图的关键术语和方法。顾名思义,它就像使用数据创建一个地图,在底层逻辑上提供一个抽象的表示。它们提供了一种有效的方式来显示和定位基于键的值,也可以根据键来插入和删除值。