哈希表的python实现

一、哈希表

        哈希表(Hash Table,又称为散列表),一个通过哈希函数来计算数据的存储位置的数据结构,是一种线性表的存储结构。

        哈希表由一个直接寻址表和一个哈希函数组成,哈希函数 h(k) 将关键字 k 作为自变量,返回元素的存储下标。

1、哈希函数

        哈希函数 h(k) 将关键字 k 作为自变量,计算并返回元素的存储下表。

2、直接寻址表

        将 key 为 k 的元素放到 k 位置上,适用于关键字的全域U比较小时。

直接寻址表缺点: 

        当域U很大时,需要消耗大量的内存,不实际。

        如果域U很大,而实际出现的 key 很少,则大量内存被浪费。

        无法处理关键字不是数字的情况。

3、改进的直接寻址表--哈希(Hashing)

        1、构造大小为m的寻址表T

        2、key为 k 的元素放到 h(k) 位置上

        3、h(k) 是一个函数,将其域映射到表T [ 0,1,2,3,···,m-1 ]

假设有一个长度为7的哈希表,哈希表函数 h(k) = k%7. 元素集合{14,22,3,5}的存储方式如下图:

4、哈希冲突

        由于哈希表的大小是有限的,而要存储的值的总数量是无限的,因此对于任何哈希函数,都会出现两个不同的元素映射到同一个位置上的情况,这种情况叫做哈希冲突。

        比如 h(k) = k%7.   h(0)=h(7)=h(14)=···

5、解决冲突方法

方法一、开放寻址法

        如果哈希函数返回值的位置已经有值,则可以向后探查新的位置来存储这个值。

        线性探查:如果位置 i 被占用,则探查 i+1, i+2,···

        二次探查:如果位置 i 被占用,则探查 i+1^2, i-1^2, i+2^2, i-2^2,···

        二次哈希:有 n 个哈希函数,当使用第 i 个哈希函数h1发生冲突时,则尝试使用h2,h3,···

方法二、拉链法

        哈希表的每一个位置都连接一个链表,当冲突发生时,冲突的元素将被加到该位置链表的最后。比如:h(k)=k%5

6、哈希表代码实现--拉链法

# 先写一个构建链表的函数,封装到类里面,尾插法,单个元素插入,元素查找。
class Node:
    def __init__(self, item):
        self.item = item
        self.next = None

class Linklist:
    def __init__(self):
        self.head = None   # 定义头结点
        self.tail = None   # 定义尾节点

    def create_linklist(self, element):   # 利用尾插法创建链表
        node = Node(element)
        if self.head == None:   # 当链表为空时
            # 使插入元素成为头结点和尾节点
            self.head = node
            self.tail = self.head
        else:
            self.tail.next = node   # 当链表不为空时,使用尾插法
            self.tail = node
        return self.head

    def linklist_find(self, obj):   # 元素的查询
        curnode = self.head
        while curnode:
            if curnode.item == obj:
                return True
            curnode = curnode.next
        else:
            return False

    def linklist_print(self):   # 链表打印
        curnode = self.head
        while curnode:
            print(curnode.item, end=" ")
            curnode = curnode.next


class Hash_table():
    def __init__(self, size=101):   # size哈希表长度
        self.size = size
        self.T = [Linklist() for _ in range(size)]   # 定义一个size长度的列表,列表中每个位置都是空链表

    # 哈希函数
    def h(self, element):
        return element % self.size  # 返回哈希函数计算生成的下标

    # 哈希表插入
    def insert_hash(self,k):
        i = self.h(k)
        if self.T[i].linklist_find(k):   # 在列表中对应的位置链表插入
            print('Duplicated insert')
        else:
            self.T[i].create_linklist(k)

    # 列表形式插入
    def insert_hash_list(self, li):
        for var in li:
            self.insert_hash(var)

    def print_hash(self):   # 打印哈希表
        for linklist in self.T:
            linklist.linklist_print()


ht = Hash_table(5)
ht.insert_hash_list([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])
ht.print_hash()

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值