python散列表实现查找,使用了多种算法并测试对比进行了性能分析(查找效率)

简介: 散列表实现查找本章是填补之前文章的坑,对哈希算法进行了实现,使用了平方取中法/除留余数法进行哈希映射,使用开放地址与公共溢出区解决冲突,同时对不同方法进行了性能分析对比,最后进行了总结。可以转载,但请声明源链接:文章源链接justin3go.com(有些latex公式某些平台不能渲染可查看这个网站)

散列表实现查找

本章是填补之前文章的坑,对哈希算法进行了实现,使用了平方取中法/除留余数法进行哈希映射,使用开放地址与公共溢出区解决冲突,同时对不同方法进行了性能分析对比,最后进行了总结。

可以转载,但请声明源链接:文章源链接justin3go.com(有些latex公式某些平台不能渲染可查看这个网站)

Library



import pandas as pd
import numpy as np
import time

读取数据


df = pd.read_excel('重庆市印刷和记录媒介复制业754.xlsx')
df.dropna(axis=0, how='any')  # 去除非数
print("表长为:", len(df))
df.head()
表长为: 75

image.png

get_nms


def get_nums(s):
    '''
    逐位相加其ASCII码
    '''
    s = str(s)
    nums = 0
    for s0 in s:
        if(s0 == '-'):
            continue
        try:
            nums += ord(s0)
        except:
            print("error: ",s)
    return nums
get_nums("重庆优得利印刷有限公司")


276879


平方取中法


df['nums_电话'] = df['电话'].apply(get_nums)
df['nums_电话^2'] = df['nums_电话'].apply(lambda x: np.square(x))
df['nums_企业名称'] = df['企业名称'].apply(get_nums)
# df['nums_电话^4'] = df['nums_电话^2'].apply(lambda x: np.square(x))
df.head()


image.png

def get_mid(x):
    '''
    取中间三位数作为地址
    '''
    return int(x/10)%1000


df['adr_电话'] = df['nums_电话^2'].apply(get_mid)
df['adr_企业名称'] = df['nums_企业名称'].apply(get_mid)
df.head(100)


image.png

image.png

除留余数法


df['adr_电话_1'] = df['nums_电话^2']%1007
df['adr_企业名称_1'] = df['nums_企业名称']%1007
df.head()

image.png

创建哈希表(分别使用开发地址与公共溢出区解决冲突)


#初始化为全0
# 开放地址法所使用的hash
hash_map_tele = np.zeros(32000)
hash_map_name = np.zeros(8000)
# 公共溢出区所使用的hash
hash_map_tele_1 = np.zeros(2100)
hash_map_name_1 = np.zeros(2100)
len(hash_map_tele)


400000
#探测开放地址法
def create_hash_map_tele(x, adr, df_ID):
    try:
        adr = int(x[adr])
    except:
        print('error: ', adr)
    while(hash_map_tele[adr] != 0):
        adr += 800
    hash_map_tele[adr] = x[df_ID]
def create_hash_map_name(x, adr, df_ID):
    try:
        adr = int(x[adr])
    except:
        print('error: ', adr)
    while(hash_map_name[adr] != 0):
        adr += 800
    hash_map_name[adr] = x[df_ID]
#使用公共溢出区
count1 = 0
count2 = 0
def create_hash_map_tele1(x, adr, df_ID):
    global count1
    if(hash_map_tele_1[x[adr]] == 0):
        hash_map_tele_1[x[adr]] = x[df_ID]
    else:
        hash_map_tele_1[1100 + count1] = x[df_ID]
        count1 += 1
def create_hash_map_name1(x, adr, df_ID):
    global count2
    if(hash_map_name_1[x[adr]] == 0):
        hash_map_name_1[x[adr]] = x[df_ID]
    else:
        hash_map_name_1[1100 + count2] = x[df_ID]
        count2 += 1


df.apply(create_hash_map_tele, axis=1, args=('adr_电话', 'ID'))
df.apply(create_hash_map_name, axis=1, args=('adr_企业名称', 'ID'))
df.apply(create_hash_map_tele1, axis=1, args=('adr_电话_1', 'ID'))
df.apply(create_hash_map_name1, axis=1, args=('adr_企业名称_1', 'ID'))
hash_map_tele


array([0., 0., 0., ..., 0., 0., 0.])

查找流程(平方取中+开发地址探测法)-method1


# 查找
search_method = int(input("请输入你查找关键词的类型:1,电话查找;2,企业名称查找"))
if(search_method == 1):
    tele = input("请输入你要查找对象的电话号码:")
    tele = int(tele)
    time_start = time.time()
    nums = get_mid(pow(get_nums(tele), 2))
    print("-----base_nums-----\n",nums)
    print("-----hash_map_tele_value-----\n", hash_map_tele[nums])
    print("-----开始查找-----")
    while(df['电话'][hash_map_tele[nums]] != tele):
        # print("-----tele-----\n", df['电话'][hash_map_tele[nums]])
        nums += 800
        # print('-----add_nums-----\n', nums)
        if(nums >= 32000):
            print('查找错误:无该信息')
            break
    time_end = time.time()
    if(nums < 32000):
        print("---------------你查找的信息如下:---------------\n", df.loc[hash_map_tele[nums]])
    print("---------------本次查找耗时:---------------\n",time_end-time_start)
elif(search_method == 2):
    name = input("请输入你要查找对象的企业名称:")
    time_start = time.time()
    nums = get_mid(get_nums(name))
    print("-----base_nums-----\n",nums)
    print("-----hash_map_tele_value-----\n", hash_map_name[nums])
    print("-----开始查找-----")
    while(df['企业名称'][hash_map_name[nums]] != name):
        # print("-----tele-----\n", df['企业名称'][hash_map_name[nums]])
        nums += 800
        # print('-----add_nums-----\n', nums)
        if(nums >= 8000):
            print('查找错误:无该信息')
            break
    time_end = time.time()
    if(nums < 8000):
        print("---------------你查找的信息如下:---------------\n", df.loc[hash_map_name[nums]])
    print("---------------本次查找耗时:---------------\n",time_end-time_start)
else:
    print("请选择正确的查找方式!")


-----base_nums-----
 370
-----hash_map_tele_value-----
 4.0
-----开始查找-----
---------------你查找的信息如下:---------------
 ID                          4
企业名称                      吕兴华
电话                13896015224
企业地址         重庆市璧山区大路街道天星街23号
nums_电话                   569
nums_电话^2              323761
adr_电话                    376
nums_企业名称               63703
adr_企业名称                  370
Name: 4, dtype: object
---------------查找耗时:---------------
 0.0009999275207519531


查找流程(除留余数法+公共溢出法)-method2


# 查找
search_method = int(input("请输入你查找关键词的类型:1,电话查找;2,企业名称查找"))
if(search_method == 1):
    tele = input("请输入你要查找对象的电话号码:")
    tele = int(tele)
    time_start = time.time()
    nums = get_nums(tele)%1007
    print("-----base_nums-----\n",nums)
    print("-----hash_map_tele_value-----\n", hash_map_tele_1[nums])
    print("-----开始查找-----")
    while(df['电话'][hash_map_tele_1[nums]] != tele):
        # print("-----tele-----\n", df['电话'][hash_map_tele_1[nums]])
        nums += 1
        # print('-----add_nums-----\n', nums)
        if(nums >= 2100):
            print('查找错误:无该信息')
            break
    time_end = time.time()
    if(nums < 2100):
        print("---------------你查找的信息如下:---------------\n", df.loc[hash_map_tele_1[nums]])
    print("---------------本次查找耗时:---------------\n",time_end-time_start)
elif(search_method == 2):
    name = input("请输入你要查找对象的企业名称:")
    time_start = time.time()
    nums = get_nums(name)%1007
    print("-----base_nums-----\n",nums)
    print("-----hash_map_tele_value-----\n", hash_map_name_1[nums])
    print("-----开始查找-----")
    while(df['企业名称'][hash_map_name_1[nums]] != name):
        # print("-----tele-----\n", df['企业名称'][hash_map_name_1[nums]])
        nums += 1
        # print('-----add_nums-----\n', nums)
        if(nums >= 2100):
            print('查找错误:无该信息')
            break
    time_end = time.time()
    if(nums < 2100):
        print("---------------你查找的信息如下:---------------\n", df.loc[hash_map_name_1[nums]])
    print("---------------本次查找耗时:---------------\n",time_end-time_start)
else:
    print("请选择正确的查找方式!")


-----base_nums-----
 262
-----hash_map_tele_value-----
 4.0
-----开始查找-----
---------------你查找的信息如下:---------------
 ID                           4
企业名称                       吕兴华
电话                 13896015224
企业地址          重庆市璧山区大路街道天星街23号
nums_电话                    569
nums_电话^2               323761
nums_企业名称                63703
adr_电话                     376
adr_企业名称                   370
adr_电话_1                   514
adr_企业名称_1                 262
Name: 4, dtype: object
---------------本次查找耗时:---------------
 0.005001544952392578


性能分析


df.head(10)


image.png

image.png

print("表长为:", len(df))


表长为: 754


32000与8000的来历

print("重复元素最多次数fen'bie为:")
for i in range(500):
    flag = 0
    for j in range(800):
        index = 800*i + j
        if(hash_map_tele[index] != 0):
            flag = 1
    if(flag == 0):
        print("tele_i:", i)
        break
for i in range(500):
    flag = 0
    for j in range(800):
        index = 800*i + j
        if(hash_map_name[index] != 0):
            flag = 1
    if(flag == 0):
        print("name_i:", i)
        break
tele_i: 39
name_i: 9

计算method1的ASL

c1 = 0  # 统计总的查找次数
for i in range(500):
    for j in range(800):
        index = 800*i + j
        if(hash_map_tele[index] != 0):
            c1 += (i+1)
print('method1-tele-asl:', c1/754)
c2 = 0  # 统计总的查找次数
for i in range(500):
    for j in range(800):
        index = 800*i + j
        if(hash_map_name[index] != 0):
            c2 += (i+1)
print('method1-name-asl:', c2/754)
method1-tele-asl: 12.10079575596817
method1-name-asl: 1.6498673740053051


计算method2的ASL

df1 = df.adr_电话_1.value_counts() 
print(df1)


514    39
916    33
329    32
47     31
767    31
187    29
216    29
473    28
619    27
646    26
384    26
62     26
9      25
372    25
175    21
530    20
6      20
852    19
256    18
130    18
780    17
690    17
343    16
917    16
653    15
537    15
685    13
423    12
513    11
891    11
201    10
771    10
311     9
859     7
994     7
93      6
386     5
568     5
938     5
206     4
28      4
688     3
890     3
788     2
119     2
590     1
309     1
752     1
494     1
894     1
434     1
Name: adr_电话_1, dtype: int64


df2 = df.adr_企业名称_1.value_counts() 
print(df2)
68      6
90      5
406     5
231     4
979     4
       ..
439     1
768     1
445     1
446     1
1006    1
Name: adr_企业名称_1, Length: 516, dtype: int64
print("有多少个元素在method2-tele基础表中,即只需查一次:",len(df1))
print("有多少个元素在method2-name基础表中,即只需查一次:",len(df2))


有多少个元素在method2-tele基础表中,即只需查一次: 51
有多少个元素在method2-name基础表中,即只需查一次: 516


# 基本表中的元素只需查一次,溢出区的元素和顺序表的查找次数是一样的,所以可以使用等差数列的计算公式进行计算,不过需要注意的就是溢出区的查找次数是从2开始的
print("method2-tele-asl:", (51 + (703*2 + (703*702)/2))/754)
print("method2-name-asl:", (516 + (238*2 + (238*237)/2))/754)


method2-tele-asl: 329.19098143236073
method2-name-asl: 38.720159151193634


最终得出结果


  • method1-tele-asl: 12.10079575596817
  • method1-name-asl: 1.6498673740053051
  • method2-tele-asl: 329.19098143236073
  • method2-name-asl: 38.720159151193634

分析


总的来说,重复元素的个数越多,哈希查找的效率就相应越低而法1的开放地址探测法对冲突的解决在本题中查找效率是明显优于公共溢出法的,但相应的占据了更大的存储空间至于平方去中法以及除留余数法在本题中映射出来的地址重复个数基本一致,故不相上下。



目录
相关文章
|
9天前
|
机器学习/深度学习 存储 算法
解锁文件共享软件背后基于 Python 的二叉搜索树算法密码
文件共享软件在数字化时代扮演着连接全球用户、促进知识与数据交流的重要角色。二叉搜索树作为一种高效的数据结构,通过有序存储和快速检索文件,极大提升了文件共享平台的性能。它依据文件名或时间戳等关键属性排序,支持高效插入、删除和查找操作,显著优化用户体验。本文还展示了用Python实现的简单二叉搜索树代码,帮助理解其工作原理,并展望了该算法在分布式计算和机器学习领域的未来应用前景。
|
25天前
|
监控 算法 安全
深度洞察内网监控电脑:基于Python的流量分析算法
在当今数字化环境中,内网监控电脑作为“守城卫士”,通过流量分析算法确保内网安全、稳定运行。基于Python的流量分析算法,利用`scapy`等工具捕获和解析数据包,提取关键信息,区分正常与异常流量。结合机器学习和可视化技术,进一步提升内网监控的精准性和效率,助力企业防范潜在威胁,保障业务顺畅。本文深入探讨了Python在内网监控中的应用,展示了其实战代码及未来发展方向。
|
1月前
|
机器学习/深度学习 人工智能 算法
基于Python深度学习的眼疾识别系统实现~人工智能+卷积网络算法
眼疾识别系统,本系统使用Python作为主要开发语言,基于TensorFlow搭建卷积神经网络算法,并收集了4种常见的眼疾图像数据集(白内障、糖尿病性视网膜病变、青光眼和正常眼睛) 再使用通过搭建的算法模型对数据集进行训练得到一个识别精度较高的模型,然后保存为为本地h5格式文件。最后使用Django框架搭建了一个Web网页平台可视化操作界面,实现用户上传一张眼疾图片识别其名称。
130 5
基于Python深度学习的眼疾识别系统实现~人工智能+卷积网络算法
|
2天前
|
算法 数据安全/隐私保护 计算机视觉
基于FPGA的图像双线性插值算法verilog实现,包括tb测试文件和MATLAB辅助验证
本项目展示了256×256图像通过双线性插值放大至512×512的效果,无水印展示。使用Matlab 2022a和Vivado 2019.2开发,提供完整代码及详细中文注释、操作视频。核心程序实现图像缩放,并在Matlab中验证效果。双线性插值算法通过FPGA高效实现图像缩放,确保质量。
|
5天前
|
监控 算法 安全
内网桌面监控软件深度解析:基于 Python 实现的 K-Means 算法研究
内网桌面监控软件通过实时监测员工操作,保障企业信息安全并提升效率。本文深入探讨K-Means聚类算法在该软件中的应用,解析其原理与实现。K-Means通过迭代更新簇中心,将数据划分为K个簇类,适用于行为分析、异常检测、资源优化及安全威胁识别等场景。文中提供了Python代码示例,展示如何实现K-Means算法,并模拟内网监控数据进行聚类分析。
28 10
|
23天前
|
存储 算法 安全
控制局域网上网软件之 Python 字典树算法解析
控制局域网上网软件在现代网络管理中至关重要,用于控制设备的上网行为和访问权限。本文聚焦于字典树(Trie Tree)算法的应用,详细阐述其原理、优势及实现。通过字典树,软件能高效进行关键词匹配和过滤,提升系统性能。文中还提供了Python代码示例,展示了字典树在网址过滤和关键词屏蔽中的具体应用,为局域网的安全和管理提供有力支持。
50 17
|
1月前
|
存储 监控 算法
员工电脑监控屏幕场景下 Python 哈希表算法的探索
在数字化办公时代,员工电脑监控屏幕是保障信息安全和提升效率的重要手段。本文探讨哈希表算法在该场景中的应用,通过Python代码例程展示如何使用哈希表存储和查询员工操作记录,并结合数据库实现数据持久化,助力企业打造高效、安全的办公环境。哈希表在快速检索员工信息、优化系统性能方面发挥关键作用,为企业管理提供有力支持。
45 20
|
27天前
|
存储 人工智能 算法
深度解密:员工飞单需要什么证据之Python算法洞察
员工飞单是企业运营中的隐性风险,严重侵蚀公司利润。为应对这一问题,精准搜集证据至关重要。本文探讨如何利用Python编程语言及其数据结构和算法,高效取证。通过创建Transaction类存储交易数据,使用列表管理订单信息,结合排序算法和正则表达式分析交易时间和聊天记录,帮助企业识别潜在的飞单行为。Python的强大功能使得从交易流水和沟通记录中提取关键证据变得更加系统化和高效,为企业维权提供有力支持。
|
26天前
|
存储 算法 安全
U 盘管控情境下 Python 二叉搜索树算法的深度剖析与探究
在信息技术高度发达的今天,数据安全至关重要。U盘作为常用的数据存储与传输工具,其管控尤为关键。本文探讨Python中的二叉搜索树算法在U盘管控中的应用,通过高效管理授权U盘信息,防止数据泄露,保障信息安全。二叉搜索树具有快速插入和查找的优势,适用于大量授权U盘的管理。尽管存在一些局限性,如树结构退化问题,但通过优化和改进,如采用自平衡树,可以有效提升U盘管控系统的性能和安全性。
26 3
|
1月前
|
存储 算法 Serverless
剖析文件共享工具背后的Python哈希表算法奥秘
在数字化时代,文件共享工具不可或缺。哈希表算法通过将文件名或哈希值映射到存储位置,实现快速检索与高效管理。Python中的哈希表可用于创建简易文件索引,支持快速插入和查找文件路径。哈希表不仅提升了文件定位速度,还优化了存储管理和多节点数据一致性,确保文件共享工具高效运行,满足多用户并发需求,推动文件共享领域向更高效、便捷的方向发展。

热门文章

最新文章