数据结构:哈希表(HashTable)

数据结构作业

Problem 03: Linked HashTable

一、哈希表

  1. 功能:请实现一个链式的哈希表
    具体如下:
  • 1.如果您有一个带有填充因子“0.5”和“100”个桶的哈希表,那么一旦它存储key-value元素对数超过“0.5 * 100 = 50”个元素,就需要使捅数量扩充到“200”个 即需要实现函数:_resize(), 处理扩容需要完成的方法:
  • 2.is_empty(self) - 判断self是否为空HashTable。
  • 3.__getitem__(self, key) - 返回self[key]。如果哈希表中不存在`key`,返回defaultvalue。如果哈希表中不存在`key`并且defaultvalueNone,需要引发`KeyError`。以及 get(self, key, defualtvalue=None)
  • 4.__setitem__(self, key, value) - 如果key存在,将 self[key] 设置为 value,否则加入一个新的键值对。
  • 5.find_bucket(self, key) - 返回self[key]存储在哈希表的桶号。
  • 6.remove(self, key, defaultvalue=None) - 删除self[key],并返回对应的值。如果哈希表中不存在`key`,则返回defaultvalue。如果哈希表中不存在`key`并且defaultvalueNone,需要引发`KeyError`。
  • 7.__iter__(self) - 返回哈希表中键的迭代器。
  • 8.values(self) - 应该是一个生成器,返回self中value的迭代器。
  • 9.items(self) - 应该是一个生成器,将哈希表的数据项作为元组 (key,value),返回self中数据项的迭代器。
  1. 提供了部分可供使用的接口:(鼓励自行实现接口)

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打印

  1. 代码部分
class Node:
    def __init__(self, node_data):
        self._data = node_data
        self._next = None

    def get_data(self):
        return self._data

    def set_data(self, node_data):
        self._data = node_data

    def get_next(self):
        return self._next

    def set_next(self, node_next):
        self._next = node_next

    next = property(get_next, set_next)

    def __str__(self):
        return str(self._data)

class MyLinkedList:

    def __init__(self):
        self.head = None

    def is_empty(self):
        return self.head is None

    def add(self, item):
        temp = Node(item)
        temp.set_next(self.head)
        self.head = temp

    def size(self):
        current = self.head
        count = 0
        while current is not None:
            count = count + 1
            current = current.get_next()
            return count

    def search(self, item):
        current = self.head
        count = 0
        while current is not None:
            count += 1
            if current.get_data() == item:
                return [True,count]
            current = current.get_next()
        return [False,None]

    def removenode(self, item):
        current = self.head
        previous = None

        while current is not None:
            if current.get_data() == item:
                break
            previous = current
            current = current.get_next()

        if current is None:
            raise ValueError("{} is not in the list".format(item))
        if previous is None:
            self.head = current.get_next()
        else:
            previous.set_next(current.get_next())

class ExtensibleHashTable:

    def __init__(self,capacity=16,factor=0.125):
        self.capacity = capacity    
        self.size = 0 
        self.slots = [None]*capacity
        self.value_s = [None]*capacity
        self.factor = factor

    def _hash_function(self, key):
        return (id(key) // 10) % self.capacity

    def _resize(self):
        self.size = 0
        old_slots, old_values = self.slots, self.value_s
        self.capacity *= 2
        self.slots = [None] * self.capacity
        self.value_s = [None] * self.capacity
        for i in range(len(old_slots)):
            if old_slots[i] is None:
                continue
            current = old_slots[i].head
            current_value = old_values[i].head
            while current is not None:
                self.__setitem__(current.get_data(), current_value.get_data())
                current = current.get_next()
                current_value = current_value.get_next()

    def __setitem__(self, key, value):
        hash_value = self._hash_function(key)
        if self.slots[hash_value] is None:
            self.slots[hash_value] = MyLinkedList()
            self.slots[hash_value].add(key)
            self.value_s[hash_value] = MyLinkedList()
            self.value_s[hash_value].add(value)
            self.size += 1
            factor = self.size / self.capacity
            if factor >= self.factor:
                self._resize()
        else:
            if self.slots[hash_value].search(key)[0] is True:
                current = self.value_s[hash_value].head
                count = 0
                while current is not None:
                    count += 1
                    if count == self.slots[hash_value].search(key)[1]:
                        current.set_data(value)
                        break
                    current = current.get_next()
            else:
                self.slots[hash_value].add(key)
                self.value_s[hash_value].add(value)

    def __getitem__(self, key,defautvalue = None):
        start_slot = self._hash_function(key)
        if self.slots[start_slot] is None:
            return "KeyError"
        elif self.slots[start_slot].search(key)[0] is True:
            current = self.value_s[start_slot].head
            count = 0
            while current is not None:
                count += 1
                if count == self.slots[start_slot].search(key)[1]:
                    return current.get_data()
                current = current.get_next()
        else:
            return defautvalue

    def is_empty(self):
     
        return self.size == 0

    def remove(self,key,defautvalue = None):
        remove_slot = self._hash_function(key)
        if self.slots[remove_slot] is None:
            return "KeyError"
        elif self.slots[remove_slot] is not None and self.slots[remove_slot].search(key)[0] is True:
            current = self.slots[remove_slot].head
            current_value = self.value_s[remove_slot].head
            previous = None
            previous_value = None
            while True:
                remove_value = current_value.get_data()
                if current.get_data() == key:
                    break
                previous = current
                previous_value = current_value
                current = current.get_next()
                current_value = current_value.get_next()
            if previous is None:
                self.slots[remove_slot].head = current.get_next()
                self.value_s[remove_slot].head = current_value.get_next()
                self.size -= 1
                return remove_value
            else:
                previous.set_next(current.get_next())
                previous_value.set_next(current_value.get_next())
                self.size -= 1
                return remove_value
        else:
            return defautvalue

    def get(self,key,value = None):
        for bucket in range(self.capacity):
            if self.slots[bucket] is not None and self.slots[bucket].search(key)[0] is True:
                return bucket
        else:
            return value

    def __iter__(self):
        for key in self.slots:
            if key is not None:
                current = key.head
                while current is not None:
                    yield(current.get_data())
                    current = current.get_next()

    def values(self):
        lst = []
        for value in self.value_s:
            if value is not None:
                current = value.head
                while current is not None:
                    lst.append(current.get_data())
                    current = current.get_next()
        return lst

    def items(self):
        lst = []
        for item in self.slots:
            if item is not None:
                current = item.head
                while current is not None:
                    tup = []
                    tup.append(current.get_data())
                    tup.append(self.__getitem__(current.get_data()))
                    tup = tuple(tup)
                    lst.append(tup)
                    current = current.get_next()
        return lst

    def keys(self):
        return self.__iter__()
  1. 演示结果请添加图片描述
  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值