链接法散列表 python实现
具有关键字k的节点,通过散列函数h, 把节点存放在散列表T[0…m-1]的槽h(k)内,h(k)为散列值,但是存在一个问题,不同的关键字可能有相同的散列值,存放在散列表内会发生冲突,因此,可以通过链接法,通过在每个槽内存放一个指向双向链表或单向链表的指针,把具有相同散列值的节点存放在一条链表内从而解决冲突。
class Node(object):
def __init__(self, key):
self.key = key
self.next = None
self.pre = None
def __repr__(self):
value = '{%d}' % (self.key)
return value
class HashTable(object):
'''
散列表的实现(链接法)
'''
def __init__(self, T = []):
self.T = T #散列表
self.m = len(self.T) #散列表的容量(槽的数目)
self.size = 0 #散列表中所有元素的数量
def _hash(self, key):
#定义散列函数
return abs(key) % self.m
def insert(self, node):
#插入一个节点
k = self._hash(node.key) #散列值
if self.T[k] == None: #此链表内没有值的情况
self.T[k] = node
node.next = None
node.pre = None
else:
node.next = self.T[k] #此链表内有值的情况
self.T[k].pre = node
self.T[k] = node
self.T[k].pre = None
self.size += 1
def search(self, key): #按关键字搜索
k = self._hash(key)
current = self.T[k]
while current != None and current.key != key:
current = current.next
if current == None : #没有找到时
return "keyerror"
return True
def delete(self, node): #删除散列表的指定节点
k = self._hash(node.key)
if node == self.T[k]:
self.T[k] == None
elif node.next == None:
node.pre.next = None
else:
node.next.pre = node.pre
node.pre.next = node.next
self.size -= 1
return node
def print(self): #可视化散列表
res = [None for _ in range(self.m)]
for i in range(self.m):
k = self.T[i]
line = ''
while k:
line += '%s' %k
k = k.next
if k:
line += '<=>'
res[i] = line
print(res)
if __name__=='__main__':
T = HashTable([None for _ in range(10)])
nodes = []
for i in range(31):
node = Node(i)
nodes.append(node)
T.print()
T.insert(nodes[0])
T.print()
T.insert(nodes[5])
T.print()
T.insert(nodes[9])
T.print()
T.insert(nodes[10])
T.print()
T.insert(nodes[20])
T.print()
T.insert(nodes[30])
T.print()
T.delete(nodes[20])
T.print()
输出结果:
['', '', '', '', '', '', '', '', '', '']
['{0}', '', '', '', '', '', '', '', '', '']
['{0}', '', '', '', '', '{5}', '', '', '', '']
['{0}', '', '', '', '', '{5}', '', '', '', '{9}']
['{10}<=>{0}', '', '', '', '', '{5}', '', '', '', '{9}']
['{20}<=>{10}<=>{0}', '', '', '', '', '{5}', '', '', '', '{9}']
['{30}<=>{20}<=>{10}<=>{0}', '', '', '', '', '{5}', '', '', '', '{9}']
['{30}<=>{10}<=>{0}', '', '', '', '', '{5}', '', '', '', '{9}']
复杂度分析
插入时间复杂度:O(1)
查找时间复杂度:O(1)
删除时间复杂度:O(1)
(给定节点删除时间复杂度为O(1), 如给出节点关键字k删除则需要O(n))