基于QT(C++)实现查找算法图形化(数据结构课程设计)

数据结构课程设计----查找算法

(一)需求和规格说明

问题描述:实现多种查找算法(顺序表、树表、散列表三种数据类型不小于

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

注:更多内容可关注微信公众号【神仙别闹】,如当前文章或代码侵犯了您的权益,请私信作者删除!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

神仙别闹

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

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

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

打赏作者

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

抵扣说明:

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

余额充值