数据结构实践准备
题目一 学生成绩档案管理系统
1.1实验内容
①学生信息录入,信息包括学号、姓名、专业、四门课成绩、总分、名次;
②系统可对学生信息浏览、增加、删除和修改;
③按学生成绩确定名次及信息输出,双向冒泡排序、希尔排序、快速排序、堆排序。
④要求可对学生信息查询,根据学号或姓名进行查找;
⑤信息修改仅可修改四门课成绩;
⑥文件存取学生信息。
1.2编程语言与开发环境
IDEA java jdk 1.8
1.3实验思路
基本框架:
1.学生类
2.功能类
3.读取信息类
4.排序类
①双向冒泡排序
②希尔排序
③快速排序
④堆排序
5.主类
1.4算法
1.双向冒泡排序
普通冒泡排序(假设由小到大开始排序)对于给定n个记录。
①从第一个记录开始依次对相邻的两个记录进行比较,当前面的记录大于后面的记录时,交换位置。
②进行一轮比较和换位后,n个记录的最大记录将位于第n位,然后对前(n-1)个记录进行第二轮比较。
③重复该过程,直到记录剩下一个为止。
双向冒泡排序是传统冒泡气泡排序的双向进行。
①先让气泡排序由左向右进行,再来让气泡排序由右往左进行,如此完成一次排序的动作。
②使用left与right两个旗标来记录左右两端已排序的元素位置。
2.希尔排序
先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组。所有距离为dl的倍数的记录放在同一个组中。先在各组内进行直接插人排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量dt=1(dt<dt-l<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。
3.快速排序
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
4.堆排序
以大根堆为例
① 先将初始排列关键字序列(R1,R2…,Rn-1,Rn)构成大顶堆,此堆为初始的无序区.(这里是从最后一个非叶结点向前进行赛选)
②将堆顶元素R1与最后一个元素Rn交换,此时得到新的无序区(R1,R2…,Rn-1)和新的有序区(Rn),并且Rn大于无序区所有数,此后还有n-1个数;
③由于交换后新的堆顶R1可能违反堆的性质,因此需要对当前无序区(R1,R2…,Rn-1)调整为新堆(将堆顶元素向下调整使其保持大顶堆的性质,输出堆顶元素),此后还剩余n-2个数;
④重读以上算法,直到堆中仅剩一个元素为止.
题目二 隐式图的搜索问题
2.1实验内容
1)对九宫重排问题,建立图的启发式搜索求解方法;
2)用A*算法求解九宫重排问题。
实验要求
3х3九宫棋盘,放置数码为1~8的8个棋子,棋盘中留有一个空格,空格周围的棋子可以移动到空格中,从而改变棋盘的布局。根据给定初始布局和目标布局,移动棋子从初始布局到达目标布局,求解移动步骤并输出。请设计算法,使用合适的搜索策略,在较少的空间和时间代价下找到最短路径。

2.2编程语言与开发环境
IDEA java jdk 1.8
2.3 A*算法
参考:https://blog.csdn.net/weixin_44489823/article/details/89382502?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522161458596316780269829804%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=161458596316780269829804&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_click~default-1-89382502.first_rank_v2_pc_rank_v29&utm_term=A*%E7%AE%97%E6%B3%95.
寻路:
1)简化搜索区域,可将搜寻区域划分为任意简便图形;
2)搜寻区域简化为一组可以量化的节点;
3)查找最短路径
①从起点开始,把它就加入到一个由方格组成的 open list( 开放列表 ) 中,检查其相邻的方格,然后向四周扩展,直至找到目标,Open list 里的格子是路径可能会是沿途经过的,也有可能不经过。基本上 open list 是一个待检查的列表;
②把其中可走的 (walkable) 或可到达的 (reachable) 方格也加入到 open list 中。把起点 设置为这些方格的父亲 (parent node 或 parent square) ;
③把 A 从 open list 中移除,加入到 close list( 封闭列表 ) 中, close list 中的每个方格都是现在不需要再关注的;
4)路径排序(最短路径F值)
①F = G + H;
(G = 从起点移动到指定方格的移动代价,沿着到达该方格而生成的路径。
H = 从指定的方格移动到终点 B 的估算成本。这个通常被称为试探法,有点让人混淆。为什么这么叫呢,因为这是个猜测。直到我们找到了路径我们才会知道真正的距离,因为途中有各种各样的东西 ( 比如墙壁,水等 ) )
②估算 H 值,使用 Manhattan 方法,计算从当前方格横向或纵向移动到达目标所经过的方格数,忽略对角移动,然后把总数乘以 10 ;
5)继续搜索,我们从 open list 中选择 F 值最小的 节点,然后对所选择的方格作如下操作
①把它从 open list 里取出,放到 close list 中;
②检查所有与它相邻的方格,忽略其中在 close list 中或是不可走 (unwalkable) 的方格 ( 比如墙,水,或是其他非法地形 ) ,如果方格不在open lsit 中,则把它们加入到 open list 中;把我们选定的方格设置为这些新加入的方格的父亲;
③如果某个相邻的方格已经在 open list 中,则检查这条路径是否更优,也就是说经由当前方格 ( 我们选中的方格 ) 到达那个方格是否具有更小的 G 值。如果没有,不做任何操作。
2.4 A*算法总结
1.把起点加入open list。
2.重复如下过程:
a. 遍历 open list ,查找 F 值最小的节点,把它作为当前要处理的节点。
b. 把这个节点移到 close list 。
c. 对当前方格的 8 个相邻方格的每一个方格
◆ 如果它是不可抵达的或者它在 close list 中,忽略它。否则,做如下操作。
◆ 如果它不在 open list 中,把它加入 open list ,并且把当前方格设置为它的父亲,记录该方格的 F , G 和 H 值。
◆ 如果它已经在 open list 中,检查这条路径 ( 即经由当前方格到达它那里 ) 是否更好,用 G 值作参考。更小的 G 值表示这是更好的路径。如果是这样,把它的父亲设置为当前方格,并重新计算它的 G 和 F 值。如果你的 open list 是按 F 值排序的话,改变后你可能需要重新排序。
d. 停止,当你
◆ 把终点加入到了 open list 中,此时路径已经找到了,或者
◆ 查找终点失败,并且 open list 是空的,此时没有路径。
3.保存路径。从终点开始,每个方格沿着父节点移动直至起点,这就是最短路径。
题目三 文本文件单词的检索与计数
3.1实验内容
建立一个文本文件,统计给定单词在文本文件中出现的总次数及位置;
实验要求
◆文本文件中每个单词不包含空格且不跨行,单词由字符序列构成且区分大小写,统计给定单词在文本文件中出现的总次数,检索输出的某个单词出现在文本中的行号、在该行中出现的位置。
◆设计数据量大的文本,进行子串的查询处理,分析算法运行的时间效率,对所有输出的匹配位置结果进行验证,以证明算法设计和实现的正确性。
◆用朴素模式匹配算法或KMP算法实现字符串定位;
◆可正确读取,保存文本;
3.2编程语言与开发环境
IDEA java jdk 1.8
3.3朴素模式匹配算法和KMP算法
1.朴素模式匹配算法
简单来说就是:从主串s 和子串t 的第一个字符开始,将两字符串的字符一一比对,如果出现某个字符不匹配,主串回溯到第二个字符,子串回溯到第一个字符再进行一一比对。如果出现某个字符不匹配,主串回溯到第三个字符,子串回溯到第一个字符再进行一一比对…一直到子串字符全部匹配成功。
通过图片说明:

回溯的步骤太多,导致效率太低。
2.KMP算法
举例说明:比如上面第一个图:当字符’d’与’g’不匹配,我们保持主串的指向不变,
主串依然指向’d’,而把子串进行回溯,让’d’与子串中’g’之前的字符再进行比对。
如果字符匹配,则主串和子串字符同时右移。
图解KPM:
第一个长条代表主串,第二个长条代表子串。红色部分代表两串中已匹配的部分,
绿色和蓝色部分分别代表主串和子串中不匹配的字符。
再具体一些:这个图代表主串"abcabeabcabcmn"和子串"abcabcmn"。


灰色部分就是红色部分字符串的最长相等前后缀,我们子串移动的结果就是让子串的红色部分最长相等前缀和主串红色部分最长相等后缀对齐。

子串位移的关键:每一个字符前的字符串都有最长相等前后缀,而且最长相等前后缀的长度是子串移位的关键。

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



