数据结构课程设计----查找算法
(一)需求和规格说明
问题描述:实现多种查找算法(顺序表、树表、散列表三种数据类型不小于
2 类),并进行对比分析。用户输入查找数据,界面动态演示基于查找过程的图形化显示。
编程任务:
(1)将图形化界面的基本布局设计好,根据选择的数据类型数目进行适当调整
(2)选取并完成所选取的查找算法,即在底层完成查找算法的代码逻辑,为后续的图形化做准备,这里我选取了 5 种算法,分别是:二分查找,索引表查找,平衡二叉树,B 树,散列表的拉链法。
(3)根据 QT 的 paintEvent 事件的特性,完成底层算法的实时动态展示。
(4)完成 4 大按钮的功能,分别是:开始演示,暂停演示,终止演示,重新初始化。
(5)对用户可能出现的不规范操作进行处理准备,防止程序的崩溃。
(二)设计
1.设计思想
首先此次设计重点除了对于不同结构种类的查找算法实现,还在于如何体现不同查找算法的查找过程。这里我选取的是 QT 来做可视化处理,利用重写 QT 的 paint 事件,该事件会在一开始就被自动调用,此后每一次更新需要自己手动更新该事件。利用此特性,我决定在某一块白板组件上展现算法的动态,将应的算法数据处理完后,在查找过程中同步调用更新函数,这样便达成了算法查找的同步图形化展示。
2.设计表示
(1)部分共同成员数据
| 成员数据类型 | 成员名 | 描述 |
| Int | length | 随机生成数据的长度 |
| Int | target | 查找的目标值 |
| int | currentIndex | 当前搜索点的值 |
| int* | nums | 随机生成的数据 |
| int | count | 查询次数 |
(2)图形化界面
| 类名 | 成员类别 | 类型 | 成员名 | 描述 |
| MainWindow | 函数 | void | generate() | 生成数据函数 |
| void | result() | 查询结果消息弹窗 | ||
| void | start(SearchcurrentSearch,BtnGroupbtngroup,intpage) | 开始按钮功能的封装 | ||
| void | pause(SearchcurrentSearch,BtnGroupbtngroup) | 暂停按钮功能封装 | ||
| void | terminate(SearchcurrentSearch,BtnGroupbtngroup) | 终止按钮功能封装 | ||
| void | reinitialize(SearchcurrentSearch,BtnGroupbtngroup,intpage) | 重新初始化功能封装 | ||
| void | initChcek() | 切换页面时初始化所有算法的选择 | ||
| void | setTarget() | 获取用户输入的查找值 | ||
| 数据 | bool | isProper | 查找目标是否合法 | |
| bool | isready | 是否已生成数据 | ||
| int | randMax | 随机数据的范围最大值 | ||
| int | randMin | 随机数据的范围最小值 | ||
| int | max | 随机数据中的最小值 | ||
| int | min | 随机数据中的最大值 | ||
| int | randLengthMax | 随机数据长度的范围最大值 | ||
| int | randLengthMin | 随机数据长度的范围最小值 |
(3)Search 类:所有算法类的父类,用于存放一些所有算法类都会用到的封装函数
| 类名 | 成员类别 | 类型 | 成员名 | 描述 |
| Search | 函数 | void | repaint() | 更新绘画 |
| void | Sleep(intmsec) | 自定义延时器 | ||
| 数据 | bool | ispause | 是否点击暂停按钮 | |
| bool | isterminate | 是否点击终止按钮 |
(4)HashSearch 类:拉链法查找
| 结构体名称 | 成员数据类型 | 成员名 | 描述 |
| node | Int | data | 存储的单词 |
| node* | next | 下一个结点 | |
| bool | isSearched | 是否被搜索过 |
| 类名 | 成员类别 | 类型 | 成员名 | 描述 |
| HashSearch | 函数 | void | paintEvent(QPaintEvent*) | 绘画事件 |
| void | hashSearch() | 散列表查找对数据的处理 | ||
| void | getsignal(boolisHashSearch,intlength,inttarget,int*nums) | 获取图形化界面点击的信号,并对其解析处理 | ||
| void | searchBucket(bucket*&t,intindex) | 从 buckets 中找到指定的节点 | ||
| 数据 | bool | isfirst | 是否是第一次绘图 | |
| bool | ishash | 是否选择了 hash 查找 | ||
| bucket* | firstBucket | 指向第一个 bucket 的指针 |
(5)ListSearch 类:二分查找,索引表查找
| 类名 | 成员类别 | 类型 | 成员名 | 描述 |
| ListSearch | 函数 | void | paintEvent(QPaintEvent*) | 绘画事件 |
| void | binarySearch() | 二分查找对数据的处理 | ||
| void | getsignal(boolbinary,boolindexed,intlength,inttarget,int*nums) | 获取图形化界面点击的信号,并对其解析处理 | ||
| void | indexedSearch() | 索引表查找对数据的处理 | ||
| 数据 | bool | isBinary | 是否选择的是二分查找 | |
| bool | isIndexed | 是否选择的是索引查找 | ||
| int* | indexList | 每个索引项其中的最大值 | ||
| int* | starts | 每个索引项的起始索引值 | ||
| int* | lengths | 每个索引项的长度 |
(6)TreeSearch 类:平衡树查找,B 树查找
| 结构体名称 | 成员数据类型 | 成员名 | 描述 |
| bnode | Int | data | 存储数据 |
| bnode* | leftC | 左儿子节点 | |
| bnode* | rightC | 右儿子节点 | |
| int | level | 节点的层数 | |
| int | bf | 平衡因子 | |
| Bnode | int | keynum | 结点关键字个数 |
| int | key | 关键字数组,key[0]不使用 | |
| Bnode* | parent | 双亲结点指针 | |
| Bnode*[] | ptr | 孩子结点指针数组 |
| 类名 | 成员类别 | 类型 | 成员名 | 描述 |
| TreeSearch | 函数 | void | paintEvent() | 绘图事件 |
| void | balancedTreeSearch() | 平衡二叉树查找数据处理 | ||
| void | BTreeSearch() | B 树查找数据处理 | ||
| void | getsignal(boolisBTree,boolisbalancedTree,intlength,inttarget,int*nums) | 接收信号,决定演示哪种算法 | ||
| int | SearchNode(bnode*&target,intdata) | 查找到 data 数据的父节点 | ||
| void | paint(intx,inty,bnode*n) | 给当前节点画左右两个儿子节点的图 | ||
| void | Bpaint(intx,inty,intpx,intpy,intindex,Bnode*b) | 给 B 树的当前节点画儿子节点的图 | ||
| int | getHeight(bnode*t) | 获取以当前节点为根的二叉树的高度 | ||
| void | setBF(bnode*t) | 更新整棵树每个节点的平衡因子 | ||
| void | getBf(bnode*&target) | 获取平衡因子绝对值超过 1 的最高层次的那个节点(注意,这里我没有采用找层次最低的平衡点,因为有个 BUG 实在无法定位修复,所以采取了消耗更大的找层次最高的平衡点) | ||
| void | correct(bnodebegin,bnodetarget) | 判断当前错误属于什么型,并执行相应的修复函数 | ||
| void | getLevel(bnode*t) | 更新所有节点的层次数 | ||
| void | setIndex(Bnode*&b,intnum) | 给新关键字找到合适的位置插入 | ||
| void | reset(Bnode*&b) | 重置调整 B 树 | ||
| void | SplitBnode(Bnode&p,Bnode&q) | 将结点 p 分裂成两个结点,前一半保留,后一半移入结点 q | ||
| void | dfs(doublex,doubley,doublepx,doublepy,intindex,intlevel,Bnode*b) | 深度优先遍历 B 树,并逐层调用绘画 | ||
| void | getMaxLevel(Bnode*b) | 获取 B 树的最大深度 | ||
| void | LL(bnode*t) | 平衡二叉树 LL 型问题 | ||
| void | RR(bnode*t) | 平衡二叉树 RR 型问题 | ||
| void | LR(bnode*t) | 平衡二叉树 LR 型问题 | ||
| void | RL(bnode*t) | 平衡二叉树 RL 型问题 | ||
| 数据 | bool | isbalancedTree | 是否选择平衡二叉树按钮 | |
| bool | isBTree | 是否选择 B 树按钮 | ||
| int | r | 圆的半径 | ||
| double | angle | 平衡二叉树儿子节点的初始偏转角度 | ||
| double | addangel | 每一层改变的偏转角度量 | ||
| QQueue | q | 存储每个节点的 x,y 坐标 | ||
| QQueue<bnode*> | node | 存储节点 | ||
| QQueue<bnode*> | node_2 | 存储节点,用于广度优先遍历 | ||
| int | w | B 树关键字节点的宽度 | ||
| int | h | B 树关键字节点的高度 | ||
| int | maxLevel | B 树的最大深度 |
3.核心算法
此次课设的核心算法主要是 5 个不同的查找算法和各个不同的算法类重写的 paint 绘图事件。
首先,用户在点击生成数据按钮后,会触发 generate 函数根据设定的参数随机生成数据,并记录下数据的最大值,最小值,和查找目标值。当然根据题目的要求,我们在图形界面展示出随机数据的长度,最大值,最小值和查找目标,因为必须兼容用户可以自己设定查找目标,用户可以在展示页面直接对查找目标进行更改。用户选择对应算法后,点击开始演示按钮,触发 start 函数,该函数根据用户选择的算法和生成的数据,触发不同算法类的 getsignal 函数。
在触发对应的算法之后,因为像二分查找和索引表对数据要求必须是排序完的,所以就需要对数据进行排序处理,这里采用的冒泡排序。5 种算法诸如 binarySearch,balancedTreeSearch,BtreeSearch,indexedSearch,hashSearch 函数便是对各自算法的所需对数据进行相应的处理,比如树类的查找算法就需要重头构建相应的树,都在对应的 Search 算法中进行数据处理。处理完后即开始查找,不同于普通的算法查找,为了动态图形化显示当前查找的进度,我们通过 currentIndex 来表示当前查找节点的值,同时只要 currentIndex 变化,我们就手动调用 update 函数,经过我们设置的短暂延迟便重新绘画整个图,如此便完成了动态实时展示查找过程的效果。
逻辑实现过程:


部分查找算法流程图如下所示:

二分查找算法

平衡二叉树
(三)用户手册

程序运行将会显示出图形化界面
用户首先需要点击生成数据按钮,底层代码根据事先设定好的参数会随机生成数据,并且将其显示到图形化界面上。为了满足用户自定义查找目标的要求,除了查找目标可以自行设置,其他数据都是 readOnly,不可更改。
然后,用户需要选择对应的数据类型,根据所选择的数据类型,左下角的算法会有不同的显示,比如选择树表,那么左下角就会显示平衡二叉树和 B 树查找,一共 5 种算法供用户选择。
生成完数据并且选择好对应的算法后,用户可以点击开始演示按钮,根据对应的算法选择,便会在对应的空白处显示不同的动态图形化显示。暂停演示按钮只有在点击开始演示按钮后才可以点击,它会暂停整个查找过程,使动态图形暂停演示。终止演示会直接情况整个图,变化空白状态。重新初始化则会先清空当前演示并自动重新生成数据一次,然后开始根据新的数据立马演示。
(四)调试及测试
1.测试数据:

点击生成数据按钮
2.演示示例:

二分查找

索引表查找

B 树查找

平衡树查找

散列表查找

查找成功,以索引表为例

查找成功,以平衡二叉树为例

查找失败,以平衡二叉树为例
(五)感想
一开始写此课设的时候,自己有很多代码重复性比较大,但是发现的时候已经比较晚了,重新进行封装后,代码量大大减少,并且逻辑更加清晰,但是的确也费了不少力气。
对于此次设计,我最大的遗憾是没有结合多线程去实现,而没有了多线程,在实现一些功能上的确比较麻烦,例如终止演示,或重复点击相同的按钮等,这些操作会造成各种各样的 bug,虽然经过我的改进,以单线程也可以完成这些功能,但总体比较遗憾,因为这应该是一次难得的多线程应用机会。
再者,因为一开始图形界面的设计问题,布局过于小,导致展示空间有限,这就使得我不得不限定随机生成数据的数目最大值,不能让用户去随意设置,因为再怎么优化展示的算法,空间始终无法满足太多的数据展示。
不过,此次课设我也收获颇多,首先是对于 bfs,dfs 的不同应用场景有了更深的理解,其次,自己去查了网上的资料,独立写出了平衡二叉树和 B 树查找,并且将他们图形化,让我对于这两种的算法的理解更加深刻,同时不再像以往一样对于树结构总有种陌生感,不熟悉各种操作。
并且,通过此次课设,我体会到了合理的函数封装与类的继承关系设计的重要性,如果只是一味的按照逻辑想到哪写到哪,那当代码量逐渐庞大起来时,便会造成自己也看不懂的困境。虽然此次对于自己的设计与封装还有很多很多的不足之处,但是经过此次的尝试,我相信自己能在下一次的程序设计种,设计出更合理的程序结构。
♻️ 资源
大小: 20.2MB
➡️ 资源下载:https://download.csdn.net/download/s1t16/87415908
注:更多内容可关注微信公众号【神仙别闹】,如当前文章或代码侵犯了您的权益,请私信作者删除!

实现查找算法图形化(数据结构课程设计)&spm=1001.2101.3001.5002&articleId=159277613&d=1&t=3&u=ee3068f379474379b9980bc9c54be266)
1378

被折叠的 条评论
为什么被折叠?



