阅读目录
- 概述
- Python实现
概述
- 散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的 数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数。
Python实现
- 以google一个题目的实现来体会什么是哈希表:
- 思路图
- 需要创建三个类:HashTable类(主要操作的类),Employee类(录入员工信息)、EmpLinkList类(用链表串联起每一个员工的信息)
初步完成
# 雇员类
class Employee(object):
def __init__(self, emp_id, emp_name):
self.emp_id = emp_id
self.emp_name = emp_name
self.next = None
# 创建hashtable 管理多条链表
class HashTable(object):
def __init__(self, size):
# 不好意思,请让我先花里胡哨一把,哈哈哈
self.menu = [k for k in HashTable.__dict__ if not (k.startswith("__") and k.endswith("__"))][:-1] # 获取类中的方法
self.size = size # 表示有多少条链表
self.__emp_link_array = [None] * size # 初始化一个列表,容量大小靠传入
for i in range(self.size): # 初始化每个链表
self.__emp_link_array[i] = EmpLinkList()
def add(self, emp): # 传入一个Employee类封装的对象
# 根据 员工的id,得到该员工应该加入哪条链表
emp_link_list_no = self.hash_fun(emp.emp_id)
# 将 emp 添加到对应的链表中
self.__emp_link_array[emp_link_list_no].add(emp)
# 遍历出所有链表
def travel_link(self):
for i in range(self.size):
self.__emp_link_array[i].travel(i)
# 编写散列函数,使用一个简单的取模法
def hash_fun(self, temp_id):
return temp_id % self.size
# 创建 EmployeeLinklist 表示链表
class EmpLinkList(object):
def __init__(self):
self.__head = None
# 添加雇员到链表
def add(self, emp):
# 假定,当添加雇员时,id是自增长,即id的分配总是从小到大
# 因此我们将该雇员直接加入到本链表的最后 即可
if self.__head is None:
self.__head = emp
return # 注意这个return
# 如果不是添加第一个雇员,需要建立一个辅助指针,定位到最后
cur = self.__head
while cur.next is not None: # 注意是 cur.next
cur = cur.next
cur.next = emp
def travel(self, no):
if self.__head is None:
print("第 %d 链表为空" % (no + 1))
return
print("第 %d 链表信息为:" % (no + 1))
cur = self.__head
while cur is not None:
print('=>id = %d name = %s' % (cur.emp_id, cur.emp_name))
cur = cur.next
print()
if __name__ == '__main__':
hashtable = HashTable(7) # 创建哈希表
while True:
for no, item in enumerate(hashtable.menu):
print("%d : %s 功能" % (no + 1, item))
active_no = int(input("请输入你要执行的功能:"))
active = getattr(hashtable, hashtable.menu[active_no - 1]) # 用反射
if active_no == 1:
emp_id = int(input("请输入员工id:"))
emp_name = input("请输入员工姓名:")
emp_obj = Employee(emp_id, emp_name)
active(emp_obj)
else:
active()
- 测试结果
完整实现
# 雇员类
class Employee(object):
def __init__(self, emp_id, emp_name):
self.emp_id = emp_id
self.emp_name = emp_name
self.next = None
# 创建hashtable 管理多条链表
class HashTable(object):
def __init__(self, size):
self.menu = [k for k in HashTable.__dict__ if not (k.startswith("__") and k.endswith("__"))][:-1] # 获取类中的方法
self.size = size # 表示有多少条链表
self.__emp_link_array = [None] * size # 初始化一个列表,容量大小靠传入
for i in range(self.size): # 初始化每个链表
self.__emp_link_array[i] = EmpLinkList()
def add(self, emp): # 添加雇员,传入一个Employee类封装的对象
# 根据 员工的id,得到该员工应该加入哪条链表
emp_link_list_no = self.hash_fun(emp.emp_id)
# 将 emp 添加到对应的链表中
self.__emp_link_array[emp_link_list_no].add(emp)
def travel_link(self): # 遍历出所有链表
for i in range(self.size):
self.__emp_link_array[i].travel(i)
def find_emp(self, went_id): # 查找雇员
emp_link_list_no = self.hash_fun(went_id)
emp = self.__emp_link_array[emp_link_list_no].find_emp_info(went_id)
if emp is not None:
print("在第%d条链表中找到了 雇员 id= %d\n" % ((emp_link_list_no + 1), went_id))
else:
print("在哈希表中不存在,没有找到该雇员")
# 编写散列函数,使用一个简单的取模法
def hash_fun(self, temp_id):
return temp_id % self.size
# 创建 EmployeeLinklist 表示链表
class EmpLinkList(object):
def __init__(self):
self.__head = None
# 添加雇员到链表
def add(self, emp):
# 假定,当添加雇员时,id是自增长,即id的分配总是从小到大
# 因此我们将该雇员直接加入到本链表的最后 即可
if self.__head is None:
self.__head = emp
return # 注意这个return
# 如果不是添加第一个雇员,需要建立一个辅助指针,定位到最后
cur = self.__head
while cur.next is not None:
cur = cur.next
cur.next = emp
def travel(self, no):
if self.__head is None:
print("第 %d 链表为空" % (no + 1))
return
print("第 %d 链表信息为:" % (no + 1))
cur = self.__head
while cur is not None:
print('=>id = %d name = %s' % (cur.emp_id, cur.emp_name))
cur = cur.next
print()
def find_emp_info(self, went_id): # 如果找到,就返回emp,没找到就返回None
if self.__head is None:
print("链表为空")
return None
cur = self.__head
while cur is not None:
if cur.emp_id == went_id:
return cur # 这时cur就指向要查找的雇员
cur = cur.next
if __name__ == '__main__':
hashtable = HashTable(7) # 创建哈希表
while True:
for no, item in enumerate(hashtable.menu):
print("%d : %s 功能" % (no + 1, item))
active_no = int(input("请输入你要执行的功能:"))
active = getattr(hashtable, hashtable.menu[active_no - 1])
if active_no == 1:
emp_id = int(input("请输入员工id:"))
emp_name = input("请输入员工姓名:")
emp_obj = Employee(emp_id, emp_name)
active(emp_obj)
elif active_no == 3:
emp_id = int(input("请输入要查找的员工id:"))
active(emp_id)
else:
active()
- 可以再扩展“删除”雇员的功能,我们只需要现在 EmpLinkList中写出单链表删除的方法,然后再到HashTable中添加一个删除的方法,就行了