• 请实现一个链式的哈希表


    关注 码龄 粉丝数 原力等级 -- 被采纳 被点赞 采纳率 哀烟笙南 2024-04-16 17:10 采纳率: 33.3% 浏览 2 首页/ 数据结构与算法 / 请实现一个链式的哈希表 数据结构python 功能:请实现一个链式的哈希表 具体如下: 1.如果您有一个带有填充因子“1.5”和“100”个桶的哈希表,那么一旦它存储key-value元素对数超过“1.5 * 100 = 150”个元素,就需要使桶数量扩充到“200”个 即需要实现函数: _resize(), 处理扩容 需要完成的方法: 2.is_empty(self) - 判断self是否为空HashTable。 3.__getitem__(self, key) - 返回self[key]。如果哈希表中不存在Key,引发KeyErr或。 以及 get(self, key, defualtvalue=None) - 返回self[key]。如果哈希表中不存在Key,返回defaultvalue。如果哈希表中不存在Key并且defaultvalue是None,需要引发KeyErr或。 4.__setitem__(self, key, value) - 如果key存在,将 self[key] 设置为 value,否则加入一个新的键值对。 5.find_bucket(self, key) - 返回self[key]存储在哈希表的桶号。 6.remove(self, key, defaultvalue=None) - 删除self[key],并返回对应的值。如果哈希表中不存在,则返回defaultvalue。如果哈希表中不存在并且defaultvalue是None,需要引发或KeyErr。 7.__iter__(self) - 返回哈希表中键的迭代器。 8.values(self) - 应该是一个生成器,返回self中value的迭代器。 9.items(self) - 应该是一个生成器,将哈希表的数据项作为元组 (key,value),返回self中数据项的迭代器。 提供了部分可供使用的接口:(鼓励自行实现接口) 1.提供了Node类: 包含了 self.data()方法,获取内容 self.next,获得下一个结点 self.prior,获得前一个结点 ——此对象支持print打印 2.LinkedList类: self.add(val) 向链表中添加元素,例如 linkedlist.add( (k, v) ) self.remove(val) 移除链表中的元素 linkedlist.remove(k) 会删除以k为键的一个元素 self.is_empty() 判断链表是否为空 self.size() 统计此链表的元素数目 self.get_head().next 获得第一个元素 ——此对象支持print打印 class Node : def __init__(self, data) -> None: self._data = data self.next: Node = None self.prior: Node = None def data(self): return self._data def __str__(self) -> str: return str(self._data) class LinkedList: def __init__(self): self._head = Node("head") self._head.next = self._head self._head.prior = self._head self._size = 0 def add(self, val): new_node = Node(val) self._head.next.prior = new_node new_node.next = self._head.next self._head.next = new_node new_node.prior = self._head self._size += 1 def remove(self, key): if self.is_empty(): return None p = self._head while p is not self._head.prior: p_data = p.next.data() if type(p_data) not in (tuple, list): p_data = [p_data] if p_data[0] == key: p.next.next.prior = p p.next = p.next.next self._size -= 1 return True p = p.next return False def __getitem__(self, key): if self.is_empty(): raise Exception p = self._head res = None while p is not self._head.prior: p_data = p.next.data() if type(p_data) not in (tuple, list): p_data = [p_data] if p_data[0] == key: res = p_data[-1] break p = p.next return res def is_empty(self): return self.size() == 0 def size(self): return self._size def get_head(self): return self._head def front(self): return self._head.next.data() def __bool__(self): return self.is_empty() def __str__(self): res = [] t = self._head.next while t != self._head: res.append(str(t.data())) t = t.next return '[' + ' '.join(res) + f'], size: {self.size()}' class ExtensibleHashTable: def __init__(self, capacity=16, load_factor=2): # 桶(链表)的个数 self._capacity = capacity # 负载因子 self._load_factor = load_factor # 装着所有链表 self._buckets = [LinkedList() for _ in range(capacity)] # 当前的元素个数 self._size = 0 def __getitem__(self, key): """实现table[key]的索引方式 时间复杂度:O(k) 可以调用get方法""" pass def _resize(self): """当负载元素数量过多,则扩容""" new_table = ExtensibleHashTable(self._capacity * 2, load_factor=self._load_factor) for k, v in self.items(): new_table[k] = v self._size = new_table._size self._buckets = new_table._buckets self._capacity = new_table._capacity def __setitem__(self, key, value): pass # 如果负载过大,则_resize后添加 def find_bucket(self, key): pass # 返回buckets里面的某个链表 def is_empty(self): pass def __iter__(self): pass # 将每一个key值,通过 yield key 逐次生成 def _hash_function(self, key) -> int: """简易的哈希函数: 取余 时间复杂度:O(1)""" def keys(self): return self.__iter__() def values(self): pass # 将每一个value值,通过 yield value 逐次生成 def items(self): pass # 将每一对key-value值,通过 yield key, value 逐次生成 def remove(self, key, value=None): pass def get(self, key, value=None): """获得key对应的value""" pass def size(self): return self._size 展开全部 收起 写回答 好问题 0 提建议 追加酬金 关注问题 微信扫一扫 点击复制链接 分享 邀请回答 编辑 收藏 删除 结题 收藏 举报 追加酬金 (90%的用户在追加酬金后获得了解决方案) 当前问题酬金 ¥ 0 (可追加 ¥500) ¥ 15¥ 20¥ 50¥ 100¥ 200 支付方式 扫码支付 二维码出错 点击刷新 支付金额 15 元 提供问题酬金的用户不参与问题酬金结算和分配 支付即为同意 《付费问题酬金结算规则》 结题 再想想 删除 再等等

    3条回答 默认 最新

    • 专家-赤兔[在线] 全栈领域优质创作者 2024-04-16 17:10
      关注

      引自免费微信小程序:皆我百晓生

      首先,我们已经给出了Node和LinkedList类,接下来我们将实现ExtensibleHashTable类。为了简化哈希函数,这里我们将使用简单的取模运算符 % 来计算哈希值。以下是完整的实现:

      class ExtensibleHashTable:
      
          def __init__(self, capacity=16, load_factor=1.5):
              self._capacity = capacity
              self._load_factor = load_factor
              self._buckets = [LinkedList() for _ in range(capacity)]
              self._size = 0
      
          def _resize(self):
              new_capacity = self._capacity * 2
              new_buckets = [LinkedList() for _ in range(new_capacity)]
      
              for bucket in self._buckets:
                  current = bucket.get_head().next
                  while current is not bucket.get_head():
                      key, value = current.data()
                      index = self._hash_function(key, new_capacity)
                      new_buckets[index].add((key, value))
                      current = current.next
      
              self._buckets = new_buckets
              self._capacity = new_capacity
      
          def _hash_function(self, key, capacity=None):
              if capacity is None:
                  capacity = self._capacity
              return hash(key) % capacity
      
          def is_empty(self):
              return self._size == 0
      
          def __contains__(self, key):
              return self.get(key) is not None
      
          def __getitem__(self, key):
              index = self._hash_function(key)
              bucket = self._buckets[index]
      
              if not bucket:
                  raise KeyError(f"KeyError: '{key}'")
      
              current = bucket.get_head().next
              while current is not bucket.get_head():
                  if current.data()[0] == key:
                      return current.data()[-1]
                  current = current.next
      
              raise KeyError(f"KeyError: '{key}'")
      
          def __setitem__(self, key, value):
              index = self._hash_function(key)
      
              if self._size >= self._load_factor * self._capacity:
                  self._resize()
      
              bucket = self._buckets[index]
              if not bucket:
                  bucket.add((key, value))
              else:
                  current = bucket.get_head().next
                  while current is not bucket.get_head():
                      if current.data()[0] == key:
                          current.data()[-1] = value
                          return
                      current = current.next
      
                  bucket.add((key, value))
      
              self._size += 1
      
          def find_bucket(self, key):
              index = self._hash_function(key)
              return self._buckets[index]
      
          def __iter__(self):
              for bucket in self._buckets:
                  current = bucket.get_head().next
                  while current is not bucket.get_head():
                      yield current.data()[0]
                      current = current.next
      
          def values(self):
              for bucket in self._buckets:
                  current = bucket.get_head().next
                  while current is not bucket.get_head():
                      yield current.data()[-1]
                      current = current.next
      
          def items(self):
              for bucket in self._buckets:
                  current = bucket.get_head().next
                  while current is not bucket.get_head():
                      yield current.data()
                      current = current.next
      
          def remove(self, key, defaultvalue=None):
              index = self._hash_function(key)
              bucket = self._buckets[index]
      
              if not bucket:
                  if defaultvalue is None:
                      raise KeyError(f"KeyError: '{key}'")
                  else:
                      return defaultvalue
      
              current = bucket.get_head().next
              prev = bucket.get_head()
              removed = False
      
              while current is not bucket.get_head():
                  if current.data()[0] == key:
                      removed = True
                      prev.next = current.next
                      current.next.prior = prev
                      self._size -= 1
                      break
                  prev = current
                  current = current.next
      
              if removed:
                  return current.data()[-1]
              elif defaultvalue is None:
                  raise KeyError(f"KeyError: '{key}'")
              else:
                  return defaultvalue
      
          def get(self, key, defaultvalue=None):
              try:
                  return self[key]
              except KeyError:
                  if defaultvalue is None:
                      raise
                  else:
                      return defaultvalue
      
          def size(self):
              return self._size
      

      这个实现中,我们使用了LinkedList类来存储每个桶中的节点,并实现了所有的指定方法。注意,这里的哈希函数非常简单,实际应用中可能需要更复杂的哈希函数以减少冲突。

      展开全部

      评论 编辑记录
    • Kwan的解忧杂货铺 Java领域优质创作者 2024-04-16 17:10
      关注

      下午好🌅🌅🌅
      本答案参考ChatGPT-3.5

      问题:请实现一个链式的哈希表

      解决方案:

      1. 定义一个哈希表类ExtensibleHashTable

      2. 初始化时,设置桶的数量为传入的capacity,利用链表实现桶

      3. 定义负载因子为load_factor

      4. 实现_resize()方法,当哈希表中元素数量超过负载因子乘以桶的数量时,将桶的数量扩容为原来的两倍,然后重新计算哈希值,将所有元素重新哈希到扩容后的哈希表中

      5. 实现__getitem__(self, key)方法,返回self[key]。如果哈希表中不存在Key,引发KeyErr异常

      6. 实现__setitem__(self, key, value)方法,如果key存在,将self[key]设置为value,否则加入一个新的键值对。如果负载因子过大,则调用_resize()方法进行扩容

      7. 实现find_bucket(self, key)方法,返回self[key]存储在哈希表的桶号

      8. 实现is_empty(self)方法,判断哈希表是否为空

      9. 实现__iter__(self)方法,返回哈希表中键的迭代器

      10. 实现values(self)方法,返回哈希表中所有value的迭代器

      11. 实现items(self)方法,返回哈希表中所有数据项的迭代器,每个数据项是一个元组(key, value)

      12. 实现remove(self, key, defaultvalue=None)方法,删除self[key]并返回对应的值。如果哈希表中不存在key,则返回defaultvalue。如果哈希表中不存在key,并且defaultvalue是None,则引发KeyErr异常

      13. 定义一个Node类表示链表中的节点,包含self.data()方法用于获取节点值,以及self.nextself.prior用于指向下一个和上一个节点

      14. 定义一个LinkedList类表示链表,提供add(val)方法向链表中添加元素,remove(key)方法移除链表中的元素,is_empty()方法判断链表是否为空,size()方法统计链表中的元素数目,get_head().next方法获取第一个元素,front()方法获取第一个元素的值

      15. ExtensibleHashTable类中调用LinkedList类实现哈希表中的桶

      展开全部

      评论
    • GISer Liu 2024-04-16 18:45
      关注

      该回答引用自GPT-3.5,由博主GISer Liu编写:

      首先,我们需要分析一下问题的关键点:

      1. 哈希表的设计与功能 :需要实现一个链式哈希表,包括动态扩容、元素的增删改查等功能。
      2. 负载因子与扩容策略 :当元素个数超过负载因子与桶的乘积时,进行扩容,扩容后桶的数量变为原来的两倍。
      3. 链表的实现 :给出了已实现的链表和节点类,可以在哈希表中使用这些类。
      4. 哈希函数 :给出了一个简单的哈希函数,即取余操作。
      5. 具体方法的实现 :包括判断是否为空、获取元素、设置元素、查找桶、迭代器等方法的实现。
        基于以上分析,我们可以按照以下步骤来实现哈希表:
      6. 设计哈希表结构 :确定哈希表的数据结构,包括桶的数量、负载因子、已存储元素数量等属性。
      7. 实现哈希函数 :编写哈希函数,将键映射到桶的索引。
      8. 实现扩容方法 :编写 _resize() 方法,在需要扩容时调用该方法。
      9. 实现基本功能方法 :包括 __getitem__, __setitem__, find_bucket, is_empty 等方法的实现。
      10. 实现迭代器方法 :编写 __iter__, keys, values, items 等方法,支持对哈希表进行迭代。
      11. 实现其他方法 :根据需求实现剩余的方法,如删除元素的 remove 方法等。
        接下来,我们可以根据以上思路逐步完成代码实现。以下是我对代码的修改和补充:
        pythonCopy code
        class ExtensibleHashTable:
        def __init__(self, capacity=16, load_factor=2):
        # 桶(链表)的个数
        self._capacity = capacity
        # 负载因子
        self._load_factor = load_factor
        # 装着所有链表
        self._buckets = [LinkedList() for _ in range(capacity)]
        # 当前的元素个数
        self._size = 0
        def __getitem__(self, key):
        """实现table[key]的索引方式 时间复杂度:O(k)  可以调用get方法"""
        return self.get(key)
        def _resize(self):
        """当负载元素数量过多,则扩容"""
        new_capacity = self._capacity * 2
        new_table = ExtensibleHashTable(new_capacity, load_factor=self._load_factor)
        for k, v in self.items():
        new_table[k] = v
        self._size = new_table._size
        self._buckets = new_table._buckets
        self._capacity = new_table._capacity
        def __setitem__(self, key, value):
        # 如果负载过大,则_resize后添加
        if self._size >= self._load_factor * self._capacity:
        self._resize()
        bucket_index = self._hash_function(key) % self._capacity
        self._buckets[bucket_index].add((key, value))
        self._size += 1
        def find_bucket(self, key):
        bucket_index = self._hash_function(key) % self._capacity
        return self._buckets[bucket_index]
        def is_empty(self):
        return self._size == 0
        def __iter__(self):
        return self.keys()
        def _hash_function(self, key) -> int:
        """简易的哈希函数: 取余  时间复杂度:O(1)"""
        return hash(key)
        def keys(self):
        for bucket in self._buckets:
        current = bucket.get_head().next
        while current != bucket.get_head():
        yield current.data()[0]
        current = current.next
        def values(self):
        for bucket in self._buckets:
        current = bucket.get_head().next
        while current != bucket.get_head():
        yield current.data()[1]
        current = current.next
        def items(self):
        for bucket in self._buckets:
        current = bucket.get_head().next
        while current != bucket.get_head():
        yield current.data()
        current = current.next
        def remove(self, key, value=None):
        bucket = self.find_bucket(key)
        removed_value = bucket.remove(key)
        if removed_value is not None:
        self._size -= 1
        return removed_value
        
        以上代码中,我实现了哈希表的基本功能,包括 __getitem__, __setitem__, find_bucket, is_empty, __iter__, keys, values, items, remove 方法。在设置元素时,如果负载因子超过阈值,会调用 _resize()
        方法进行扩容。同时,我也修正了哈希函数的实现,使其更加通用。
        接下来,你可以测试一下这些方法,看看是否能够正常运行。如果有任何问题或需要进一步解释的地方,请随时告诉我。

      如果该回答解决了您的问题,请采纳!如果没有,请私信联系或评论您的疑惑

      展开全部

      评论
    编辑
    预览

    报告相同问题?

  • 相关阅读:
    激光雷达物体检测(三):俯视图检测算法
    Java异常、继承结构、处理异常、自定义异常、SpringBoot中全局捕获处理异常
    Java 世界破破烂烂,电音小猫缝缝补补
    【泛函分析】距离空间的完备性
    4、MySql 索引浅解
    ELK企业级日志分析系统
    企业级自定义表单引擎解决方案(十一)--表单规则引擎1
    java计算机毕业设计springboot+vue软件项目测试过程管理系统
    使用 Dockerfile 构建生产环境镜像
    Linux压缩、解压缩以及打包命令
  • 原文地址:https://ask.csdn.net/questions/8089462