数据结构课设 BloomFilter(报告)

题目及要求

(1)问题描述
布隆过滤器是由巴顿.布隆于一九七零年提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。假定需要存储一亿个电子邮件地址,首先建立一个十六亿二进制(比特),即两亿字节的向量,然后将这十六亿个二进制全部设置为零。对于每一个电子邮件地址X,可以用八个不同的散列函数(H1,H2,…,H8)产生八个从1到十六亿之间中的八个自然数g1,g2,…,g8。然后将这八个自然数对应的八个位置的二进制全部设置为一。同样的方法对这一亿个email地址都进行处理后,一个针对这些email地址的布隆过滤器就建成了。如图所示:

在这里插入图片描述

现在看看如何用布隆过滤器来实现一个电子邮件地址过滤器,首先将那些放在黑名单上的电子邮件地址放在布隆过滤器中。当检测一个可疑的电子邮件地址Y是否在黑名单中,仍用相同的八个随机数产生器(H1,H2,…,H8)对这个邮件地址产生八个自然数s1,s2,…,s8,这八个自然数对应的八个二进制位分别是t1,t2,…,t8。如果Y在黑名单中,显然,t1,t2,…,t8对应的八个二进制一定是一。这样在遇到任何在黑名单中的电子邮件地址,都能准确地发现。
布隆过滤器决不会漏掉任何一个在黑名单中的可疑地址。但是,它有一条不足之处。也就是它有极小的可能将一个不在黑名单中的电子邮件地址判定为在黑名单中,因为有可能某个好的邮件地址正巧对应个八个都被设置成一的二进制位。但这种可能性很小,此处将它称为误识概率。在上面的例子中,误识概率在万分之一以下。
因此布隆过滤器的好处在于快速,省空间。但是有一定的误识别率。常见的补救办法是在建立一个小的白名单,存储那些可能别误判的邮件地址。
(2)课程设计目的
学习BloomFilter结构,能应用该结构解决一些实际问题。
(3)基本要求
①定义BloomFilter结构的ADT,该ADT应支持在BloomFilter中加入一个新的数据,查询数据是否在此过滤器中,并完成该结构的设计和实现。
②应用BloomFilter结构拼写检查,许多人都对Word的拼写检查功能非常了解,当用户拼错一个单词的时候,Word会自动将这个单词用红线标注出来。Word的具体工作原理不得而知,但另一个拼写检查器UNIXspell-checkers这个软件中就用到了BloomFilter。UNIXspell-checkers将所有的字典单词存成BloomFilter数据结构,而后直接在BloomFilter上进行查询。本课程设计要求针对C语言设计和实现上述拼写检查器,即当写了一个正确的关键词,如int时,给该词标上颜色,如蓝色。
③针对上述C语言关键词拼写检查器进行分析,如错误分析,设计散列函数个数分析,运行时间复杂性、空间复杂性的分析。
④上述C语言关键词拼写检查器最好是在VC++或Java等可视化开发环境下实现。
⑤上述C语言关键词拼写检查器最好能支持所有的C++关键词。
(4)实现提示
BloomFilter结构中的散列函数(包括散列函数的个数和散列函数的设计)是本题目中需要深入思考的一个环节。

内容简介

我这次的课程设计主要完成了
(1)定义BloomFilter结构的ADT,该ADT应支持在BloomFilter中加入一个新的数据,查询数据是否在此过滤器中,并完成该结构的设计和实现。
(2)应用BloomFilter结构拼写检查,许多人都对Word的拼写检查功能非常了解,当用户拼错一个单词的时候,Word会自动将这个单词用红线标注出来。Word的具体工作原理不得而知,但另一个拼写检查器UNIXspell-checkers这个软件中就用到了BloomFilter。UNIXspell-checkers将所有的字典单词存成BloomFilter数据结构,而后直接在BloomFilter上进行查询。本课程设计要求针对C语言设计和实现上述拼写检查器,即当写了一个正确的关键词,如int时,给该词标上颜色,如蓝色。
(3)针对上述C语言关键词拼写检查器进行分析,如错误分析,设计散列函数个数分析,运行时间复杂性、空间复杂性的分析。
(4)用QT设计出了一个代码编辑器,可以对已经添加的关键词进行高亮处理。
(5)我设计的这个代码编辑器,还能够支持复制、粘贴、剪切、删除和撤销等文本操作。
(6)同时利用QT还可以很方便的,选择自己喜欢的图片作为背景。

设计

(1)布隆过滤器的设计
布隆过滤器的设计最主要考虑的两个问题就是散列函数的个数的选择以及散列函数的设计。
1) 散列函数个数的选择
为了使得布隆过滤器的误判概率降到1%以下,此处散列函数的个数应该选择为七个。
以下地址是一个免费的在线布隆过滤器在线计算的网址:
https://krisiver.github.io/bloom-calculator/
经过一定的建模分析后,预计希望保存的关键字为8000个。

在这里插入图片描述
2) 散列函数设计
理论上优秀的散列函数应该包含下列性质: 1.哈希得到的值均匀分布在0-n上;2.各个哈希函数之间彼此独立,各个字符串得到的哈希值彼此独立。因此该程序的哈希函数设计宗旨是,1.获得尽量大的数值后取余,从而确保哈希值能够均匀分布。2.各个哈希函数之间无耦合关系,从而保证独立性。
(2)代码编辑器的设计
仿照C++编译器的代码框,我设计了一个代码编辑器,对录入的关键词有添加高亮的效果,这也起到了防止错误拼写的问题。
本程序使用QTextEdit控件设计文本编辑器,并继承QSyntaxHighlighter类编写子类myHighLight类以实现高亮功能。
用户通过QTextEdit控件输入文本,并将文本传至myHighLight类的构造函数用以初始化。在该构造函数中,同时初始化了QRegExp*类型变量rule以匹配关键字用并使用QTextCharFormat类型变量format高亮。
与此同时,代码编译器也支持复制、粘贴、剪切、删除和撤销等文本操作。
在这里插入图片描述
(3)添加删除关键词设计
我已经提前录入了c++所有的关键词。

此外,用户还可以根据自己的需求,添加和删除自己所需要的关键字。添加关键字我会首先使用正则表达式判断这个添加的字符串是不是单词,如果是进行下一步判断,判断这个关键词是否已经添加过了,如果已经添加过了就返回,若没有就完成正常的添加操作。
下图左上角的位置就是添加关键词的菜单栏,点击之后可以选择添加或者删除关键词。
在这里插入图片描述
删除操作需要利用到白名单。
一种可行的做法是,另外使用一个map来保存已删除的元素,在判断元素是否存在时先判断在该deletemap中是否存在,如果存在,直接false。如果不存在,再通过bloom filter进行判断。在新添加元素时,如果deletemap中存在,删除该deletemap中的该元素,再添加到bloom filter中。
(4)时间复杂度和空间复杂度分析
布隆过滤器作为数据结构时,添加和查找关键词的运算复杂度极低,而相应的删除关键词的成本相当高。原因在于,添加关键字时只需要将新的关键字进行散列后,将所得值添加到位数组。
布隆过滤器删除关键词通常采用引入白名单的方式,假设白名单共m个字符串,则遍历白名单的复杂度约为O(ms),其中s为字符串平均长度。由于查找关键词前必须遍历白名单,因此复杂度为O(x)+O(ms),其中x为散列函数个数;而添加关键词前必须要先查找关键词,故运算复杂度为O(2x)+O(mx)。同样地,布隆过滤器的空间复杂度具有类似的情况,布隆过滤器对内存的占用分为两部分,第一,白名单存储,复杂度约为O(ms);第二,二进制数组存储,复杂度约为O(n)。合计为O(ms)+ O(n)。
(三)用户手册
(1)用户可以根据自己的喜好设置布隆过滤器代码编辑器的图标。
(2)用户在代码编辑器界面可以点击左上角进行删除和添加所需要的关键字。
(3)用户添加和删除关键字只需要选中关键词,点击添加即可。
在这里插入图片描述

(4)用户只要输入了已经添加过的关键词就会有高亮的效果。
(5)用户添加到关键词必须是合法的单词。
(6)用户可以进行复制、粘贴、剪切、删除和撤销等文本操作。
(7)用户可以根据自己的喜好改变界面背景。
在这里插入图片描述

待改进

(1)借鉴vscode扩展等的效果,实现关键字自动补全的功能。
(2)借鉴word等工具,实现单词识别效果,对无法识别的单词下划红色波浪线,以警示命名变量。
(3)添加快捷键,如添加关键字、删除关键字的模态输入对话框的弹出可以与快捷键绑定起来。
(4)界面功能还不够多,之后可以再添加多一些功能。
(5)界面不够美观,可以后序添加一些更换背景的功能,使得代码编辑器更加赏心悦目。
(6)高亮颜色过于单一,之后希望实现更具不同类别关键词添加不同颜色的高亮。

个人感悟

我遇到的第一个问题是,对于这次课程设计的选题我是十分陌生的,对于布隆过滤器这对于我来说是一个之前从未听过的名词,关于为什么选这个是因为我一开始看到他利用的知识是哈希函数,而我当时也刚刚学了点哈希表相关的内容,对于这一部分还是比较感兴趣的,所以我就选择了布隆过滤器作为我的课程设计题目。
刚拿到手的时候我有点无从下手,我就去b站上搜索一些关于布隆过滤器的相关知识,我了解到布隆过滤器它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。布隆过滤器的原理是,当一个元素被加入集合时,通过K个散列函数将这个元素映射成一个位数组中的K个点,把它们置为1。检索时,我们只要看看这些点是不是都是1就(大约)知道集合中有没有它了:如果这些点有任何一个0,则被检元素一定不在;如果都是1,则被检元素很可能在。这就是布隆过滤器的基本思想。本质上布隆过滤器是一种数据结构,比较巧妙的概率型数据结构高效地插入和查询,可以用来告诉你某样东西一定不存在或者可能存在。相比于传统的 List、Set、Map 等数据结构,它更高效、占用空间更少,但是缺点是其返回的结果是概率性的,而不是确切的。但是仅仅了解这些知识是远远不够的,还要能够整理清楚思路,一步一步设计出布隆过滤器。
布隆过滤器的设计关键在于两个方面的思考,一是散列函数的个数的选择和字节数组大小的确定,二是散列函数的设计。这算是我遇到的第二个问题我在网上查阅到了大量的理论推导,看起来是相当复杂的,理解起来对于我来说也有着不小的麻烦,我在对它有一定的了解之后,偶然的机会我在一篇博文中看到了一个可以自动计算散列函数个数和字节数组大小的在线网站,所以我就偷了懒,我只要算出我这个课设所需要添加的关键词的个数和我想要的错误率,我就可以直接得到结果,这位我减去了不少的麻烦。然后就是散列函数的设计,理论上优秀的散列函数应该包含下列性质: 1.哈希得到的值均匀分布在0-n上;2.各个哈希函数之间彼此独立,各个字符串得到的哈希值彼此独立。因此我这次课设对于哈希函数设计宗旨是,1.获得尽量大的数值后取余,从而确保哈希值能够均匀分布。2.各个哈希函数之间无耦合关系,从而保证独立性。对于布隆过滤器的设计花去了我不少的时间与精力,但是也让我收获了不少的知识。
这次课程设计的要求需要我设计出一个类似于一个代码编辑器的功能,需要我对于相关的关键词进行高亮处理,这就必须要实现图形化界面的设计,我了解到Qt是一个跨平台C++图形用户界面应用程序开发框架,可以非常方便地用于开发GUI程序。其中的一些库函数和功能也可以满足我要添加关键词高亮的这一需求。但是我本身对于QT是不熟悉的,QT编译器还是因为这次做课设我才下载来使用,这也是我遇到的第三个问题,于是我又在b站上搜索一些视频来帮助我学习QT。我这次课设用到的知识还是相对基础的所以实现起来难度还算可以接受,虽然也让我多次感觉这个课设对我来说有点难,但是最后还是完成了,我也因此多学习了一个工具的使用,也是有收获的。
然后,在编程中我认识到了自己动手能力的不足,虽然相比较大一上学期而言进步很大,但是我还是不满意,有的在编程中必须看书才能写出来,有的靠百度,很少是自己写的。还好,我自己组装程序的能力还行,要不这东拼西凑的程序根本组装不了。在编程中我还认识到了,编程不能停下,如果编程的时间少了,知识忘的会很快,而且动手也会很慢。同时,同学之间的合作也很重要,每个人掌握的知识都不一样,而且掌握程度也不一样,你不会的别的同学会,所以在大家的共同努力下,编程会变得很容易。以前,没动手编程的时候觉得这些知识很容易,现在编程了才发现自己错了,大错特错了,我们这个专业最重视的就是动手编程能力,如果我们纸上写作能力很强而动手编程能力很差,那我们就白上这个专业了。计算机这个专业就是锻炼动手编程能力的,一个人的理论知识再好,没有动手编程能力,那他只是一个计算机专业的“入门者”。在编程中我们能找到满足,如果我们自己编程了一个程序,我们会感到自豪,而且充实,因为如果我们专研一个难得程序,我们会达到忘我的境界,自己完全沉浸在编程的那种乐趣之中,完全会废寝忘食。编程虽然会乏味很无聊,但是只要我们沉浸其中,你就会发现里面的乐趣,遇到难得,你会勇往直前,不写出来永不罢休;遇到容易的,你会找到乐趣。编程是很乏味,但是那是因为你没找到编程重的乐趣,你只看到了他的不好,而没有看到他的好。其实,只要你找到编程中得乐趣,你就会完全喜欢上他,不编程还好,一编程你就会变成一个两耳不闻窗外事的“植物人”。可以说只要你涉及到了计算机,你就的会编程,而且还要喜欢上他,永远和他打交道,我相信在某一天,我们一定会把他当作我们不可或缺的好朋友。
总之,通过本次课程设计,使我对《数据结构》这门课程有了更深入的理解。《数据结构》是一门实践性较强的课程,为了学好这门课程,必须在掌握理论知识的同时,加强上机实践。并且动手编程就是锻炼我们的动手能力,当然这个动手能力并不是科研上的动手能力,而是我们的动手编程能力,记住,只要你真正的喜欢上他,你就会发现其中的乐趣,我相信,只要你坚持下去,你一定会喜欢上他,把编程当作自己日常生活中一件必须做的事情。
以上就是我这次课程设计的遇到的问题与收获和我的一些个人感悟。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

桃气十足

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值