注意:
1.本博客仅供参考交流使用,请读者务必自行实践,切勿生搬硬套
2.由于笔者水平有限,若文中有错误或者可以改进之处,欢迎在评论区指出
题目
Description
散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
本题请使用散列函数:除留余数法(取关键字被某个不大于散列表表长m的数p除后所得的余数为散列地址)建立哈希表,并判断给定值是否在散列表中。
注意:本题请考虑冲突情况,即碰撞。本题请使用链冲突法解决冲突,即散列到相同地址后以建立子链的方式解决元素冲突,因此本题不考虑总元素大于散列表大小而溢出的情况。重复元素只存一个。
Input
第一行数字表示要建立的散列表的大小,第二行表示要作为元素建立散列表的整数序列(注意:元素之间以空格分开,第一行散列表大小并不表示本行元素的数量),第三行表示要插入元素的数量n,接下来n行表示待插入元素值;下一行表示要删除元素的数量m,接下来m行表示待删除元素值;下一行表示要查找元素的数量r,接下来r行表示待查找元素值。
Output
插入无输出,对于每个待删除元素,元素若在散列表中,删除即可,若不在则输出 ‘Delete Error’,注意单词间空格;执行完插入删除后,查找元素是否在散列表中,若在则在相应行输出True, 否则输出False。
Sample Input 1
5
6 9 88 20 5 6
3
4
5
10
3
11
88
10
2
6
10
Sample Output 1
Delete Error
True
False
Hint
注意:总元素数量可能会超过散列表大小。本题请使用链冲突法解决冲突,即散列到相同地址后以建立子链的方式解决元素冲突,因此本题不考虑总元素大于散列表大小而溢出的情况。重复元素只存一个。
分析:这次尝试写在注释里(注释位置不严谨,只说明用)
# -*- coding: utf-8 -*-
class Slot(object):
def __init__(self, key=None, next_slot=None):
self.key, self.next_slot = key, next_slot
# Slot是放key的槽
class HashTable(object):
def __init__(self, size=10):
self._table = [Slot()] * size
self.size = size
# 注意这里的_table,其实是在列表里放了同一个对象的size个引用,本质上只有一个空槽
def find_key(self, key):
return key % self.size
# 散列函数
def append(self, key):
index = self.find_key(key)
temp_slot = self._table[index]
if temp_slot.key is not None:
if key != temp_slot.key:
while temp_slot.next_slot is not None and key != temp_slot.next_slot.key:
temp_slot = temp_slot.next_slot
if temp_slot.next_slot is None:
temp_slot.next_slot = Slot(key)
else:
self._table[index] = Slot(key)
# 这里面的逻辑请读者自己理顺,要强调的是Slot(key)这句就补足了前文说的本质上只有一个空槽
def __delitem__(self, key):
index = self.find_key(key)
temp_slot = self._table[index]
if temp_slot.key is not None:
if key != temp_slot.key:
while temp_slot.next_slot is not None and key != temp_slot.next_slot.key:
temp_slot = temp_slot.next_slot
if temp_slot.next_slot is not None:
temp_slot.next_slot = temp_slot.next_slot.next_slot
else:
if key != temp_slot.key:
print('Delete Error')
else:
temp_slot.key = None
else:
if temp_slot.next_slot is not None:
self._table[index] = temp_slot.next_slot
else:
temp_slot.key = None
else:
print('Delete Error')
# 删除的逻辑和加入的逻辑是相似的,要注意删除每列第一个时的情况,然后__delitem__是为了可以这么写 del ...
def __contains__(self, key):
index = self.find_key(key)
temp_slot = self._table[index]
if temp_slot.key is not None:
if key != temp_slot.key:
while temp_slot.next_slot is not None and key != temp_slot.next_slot.key:
temp_slot = temp_slot.next_slot
if temp_slot.next_slot is not None:
return True
else:
if key != temp_slot.key:
return False
else:
return True
else:
return True
else:
return False
# 只要把del的del语句换成对或者否就可以了 __contains__是为了可以这样 if key in ...
@property
def table(self):
return self._table
# @property 让table变成一个属性来着,我们就可以这样: h.table[1].key = ... 或者 h.table = ...
def traverse(self):
for i in range(self.size):
temp_slot = self.table[i]
while temp_slot is not None:
if temp_slot.key is not None:
print('self.table[', i, '].key is ', temp_slot.key)
temp_slot = temp_slot.next_slot
# 这个遍历很简单,目的是为了写程序时方便观察调试
n = int(input())
h = HashTable(n)
temp = list(map(int, input().split(" ")))
for i in range(len(temp)):
h.append(temp[i])
m = int(input())
for i in range(m):
h.append(int(input()))
k = int(input())
for i in range(k):
del h[int(input())]
p = int(input())
for i in range(p):
u = int(input())
if u in h:
print('True')
else:
print('False')