数据结构与算法--哈希表 Python实现哈希表 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中添加一个删除的方法,就行了
发布了146 篇原创文章 · 获赞 37 · 访问量 7861

猜你喜欢

转载自blog.csdn.net/storyfull/article/details/103674297