中北大学软件学院算法实验报告附截图Word文档格式.docx
- 文档编号:17005854
- 上传时间:2022-11-27
- 格式:DOCX
- 页数:31
- 大小:1,002.29KB
中北大学软件学院算法实验报告附截图Word文档格式.docx
《中北大学软件学院算法实验报告附截图Word文档格式.docx》由会员分享,可在线阅读,更多相关《中北大学软件学院算法实验报告附截图Word文档格式.docx(31页珍藏版)》请在冰豆网上搜索。
4.实验原理或流程图
基本思想:
从主串S的第一个字符开始和模式T的第一个字符进行比较,若相等,则继续比较两者的后续字符;
若不相等,则从主串S的第二个字符开始和模式T的第一个字符进行比较,重复上述过程,若T中的字符全部比较完毕,则说明本趟匹配成功;
若最后一轮匹配的起始位置是n-m,则主串S中剩下的字符不足够匹配整个模式T,匹配失败。
这个算法称为朴素的模式匹配算法,简称BF算法。
设串S长度为n,串T长度为m,在匹配成功的情况下,考虑最坏情况,即每趟不成功的匹配都发生在串T的最后一个字符。
设匹配成功发生在si处,则在i-1趟不成功的匹配中共比较了(i-1)×
m次,第i趟成功的匹配共比较了m次,所以总共比较了i×
m次,因此平均比较次数是:
最坏情况是O(n×
m)。
或者写书上P39页的伪代码描述。
5.实验过程或源代码
,
#include<
>
intBF(charS[],charT[]){
intindex=0;
验结论及心得
通过本次实验我理解了使用蛮力法解决问题的特点,蛮力法的设计思想是直接基于问题本身的描述来设计算法,即不采用任何方法来精简计算过程、运算次数或者设法简化问题本身。
所以蛮力法设计的算法虽然简单易懂,但是效率却往往不是很令人满意,比如串的模式匹配问题中采用BF算法效率低下的主要原因就在于BF算法一旦主串和子串匹配失败就会产生回溯,如果能利用已有的匹配结果来减少回溯就可以提高效率,如KMP算法。
[
实验二排序问题程序设计
(1)掌握选择排序和起泡排序的基本思想
(2)掌握两种排序方法的具体实现过程
(3)在掌握的基础上编程实现两种排序方法
输入一个待排序的序列,分别用选择排序和起泡排序两种排序方法将其变换成有序的序列,输出结果,输出时要求有文字说明。
书上P42页选择排序想法三点抄上去
书上P43页冒泡排序想法三点抄上去
?
$
通过本次实验我理解了选择排序和起泡排序的基本思想。
选择排序和起泡排序都是通过将待排序记录划分成有序区和无序区,然后通过交换扩大有序区,缩小无序区,最终达到排序的目的。
两者又有区别,选择排序可以直接选出无序区的最小记录并一次插入到合适的位置上,之后不再调整,而冒泡排序则是通过两两交换实现移动的,由于很多移动无法将记录一次放置到合适的位置上,所以存在很多“无效”的移动操作,从实验结果可以看出,起泡排序的移动次数明显比选择排序要多就是因为这样的“无效”的移动操作浪费了时间。
实验三数字旋转方阵程序设计
(1)掌握分治法的设计思想
(2)掌握数字旋转方阵的具体实现过程
(3)熟练掌握二维数组的使用方法
…
(4)在掌握的基础上编程实现数字旋转方阵的实现过程
给出一个初始数据,在此数据的基础上由外层向里层填写数据,完成一个数字旋转方阵,输出结果,输出时要求有文字说明。
用二维数组data[N][N]表示N×
N的方阵,观察方阵中数字的规律,可以从外层向里层填数。
设变量size表示方阵的大小,则初始时size=N,填完一层则size=size-2;
设变量begin表示每一层的起始位置,变量i和j分别表示行号和列号,则每一层初始时i=begin,j=begin。
将每一层的填数过程分为A、B、C、D四个区域,则每个区域需要填写size–1个数字,填写区域A时列号不变行号加1,填写区域B时行号不变列号加1,填写区域C时列号不变行号减1,填写区域D时行号不变列号减1。
显然,递归的结束条件是size等于0或size等于1。
【写不下就算了】数字旋转方阵算法描述:
输入:
当前层左上角要填的数字number,左上角的坐标begin,方阵的阶数size
输出:
数字旋转方阵
@
1.如果size等于0,则算法结束;
2.如果size等于1,则data[begin][begin]=number,算法结束;
3.初始化行、列下标i=begin,j=begin;
4.重复下述操作size–1次,填写区域A
data[i][j]=number;
number++;
行下标i++;
列下标不变;
5.重复下述操作size–1次,填写区域B
行下标不变;
列下标j++;
6.重复下述操作size–1次,填写区域C
行下标i--;
7.重复下述操作size–1次,填写区域D
行下标不变,列下标j--;
(
8.调用函数Full在size-2阶方阵中左上角begin+1处从数字number开始填数;
intdata[100][100]={0};
intmaxsize=0;
voidprintData(intsize){
for(inti=0;
i<
size;
i++){
for(intj=0;
j<
j++)
printf("
%4d"
data[i][j]);
printf("
\n"
);
}
¥
printf("
}
voidFull(intnumber,intbegin,intsize){
通过本次实验,我理解了分治法解决问题的基本思想和一般过程,分治法的基本思想是“分而治之”,将大的复杂的问题分解成结构同、规模小的子问题,分解子问题要足够小以至于可以直接得出子问题的解,然后对子问题的解进行合并,最终得到原问题的解。
由于程序中采用了递归技术,需要设置递归终止的条件,在数字旋转方阵问题中,递归结束的条件是size等于0或者1。
递归问题的解决分为回溯和递推两个阶段,通过这两个过程可以求解本次实验的问题。
2016年4月8日8时至10时
实验四排序中分治法的程序设计
(1)掌握归并排序和快速排序的划分方法
(2)掌握归并排序和快速排序的具体分治策略
(3)在掌握的基础上编程两种排序方法的实现过程
给出一个初始序列,分别用归并排序和快速排序两种分治法将所给序列变换为有序序列,输出结果,输出时要求有文字说明。
%
二路归并排序的分治策略是:
(1)划分:
将待排序序列r1,r2,…,rn划分为两个长度相等的子序列r1,…,rn/2和rn/2+1,…,rn;
(2)求解子问题:
分别对这两个子序列进行排序,得到两个有序子序列;
(3)合并:
将这两个有序子序列合并成一个有序序列。
快速排序的分治策略是:
选定一个记录作为轴值,以轴值为基准将整个序列划分为两个子序列r1…ri-1和ri+1…rn,前一个子序列中记录的值均小于或等于轴值,后一个子序列中记录的值均大于或等于轴值;
分别对划分后的每一个子序列递归处理;
由于对子序列r1…ri-1和ri+1…rn的排序是就地进行的,所以合并不需要执行任何操作。
【写不下就不写了】以第一个记录作为轴值,对待排序序列进行划分的过程为:
"
(1)初始化:
取第一个记录作为基准,设置两个参数i,j分别用来指示将要与基准记录进行比较的左侧记录位置和右侧记录位置,也就是本次划分的区间;
(2)右侧扫描过程:
将基准记录与j指向的记录进行比较,如果j指向记录的关键码大,则j前移一个记录位置。
重复右侧扫描过程,直到右侧的记录小(即反序),若i<j,则将基准记录与j指向的记录进行交换;
(3)左侧扫描过程:
将基准记录与i指向的记录进行比较,如果i指向记录的关键码小,则i后移一个记录位置。
重复左侧扫描过程,直到左侧的记录大(即反序),若i<j,则将基准记录与i指向的记录交换;
(4)重复
(2)(3)步,直到i与j指向同一位置,即基准记录最终的位置。
n\n"
first,end,first,pivot-1<
firstfirst:
pivot-1,
pivot+1,end,pivot,r[pivot]);
r:
visit(r,10);
QuickSort(r,first,pivot-1);
通过本次实验,我理解了归并排序和快速排序的基本思想,两者都是将序列分为若干子序列,通过对子序列的排序,合并子序列,最终得到一个有序序列,这体现了分治法“分而治之”的思想。
`
这两种排序方法划分子序列的方式有所不同,归并排序按记录在序列中的位置进行划分,而快速排序则按照记录的值对序列进行划分,这就是两种排序方法在划分子序列上的不同之处。
实验五汉诺塔问题的程序设计
(1)掌握递归的有关概念
(2)掌握汉诺塔问题的具体求解过程
》
(3)在掌握的基础上编程实现汉诺塔的具体实现过程
在A上有按大小排序好的n个金碟,借助B的帮助,将A上的碟子移动到C上,在移动的过程中要严格按照大小顺序,不能将碟子放在比它小的上面,输出结果,输出时要求有文字说明。
汉诺塔问题可以通过以下三个步骤实现:
(1)将塔A上的n-1个碟子借助塔C先移到塔B上。
(2)把塔A上剩下的一个碟子移到塔C上。
(3)将n-1个碟子从塔B借助塔A移到塔C上。
显然,这是一个递归求解的过程。
【下方示意图画不下可省略】
:
#include<
voidHanoi(intn,charA,charB,charC){
if(n==1)
递归算法结构清晰,可读性强,而且容易用数学归纳法来证明算法的正确性,因此,它为设计算法和调试程序带来很大方便,是算法设计中的一种强有力的工具。
但是,因为递归算法是一种自身调用自身的算法,随着递归深度的增加,工作栈所需要的空间增大,递归调用时的辅助操作增多,因此,递归算法的运行效率较低。
实验六查找中减治法的程序设计
(1)掌握减治法的设计思想
(2)掌握折半查找和二叉查找的思想及实现过程
(3)在掌握的基础上编程实现两种查找方法的具体实现过程
给出一个序列及要查找的值,分别用两种查找方法实现,输出结果,输出时要求有文字说明。
折半查找基本思想:
在有序表中,取中间记录作为比较对象,若给定值与中间记录的关键码相等,则查找成功;
若给定值小于中间记录的关键码,则在中间记录的左半区继续查找;
若给定值大于中间记录的关键码,则在中间记录的右半区继续查找。
不断重复上述过程,直到查找成功,或所查找的区域无记录,查找失败。
由二叉排序树的定义,在二叉排序树root中查找给定值k的过程是:
⑴若root是空树,则查找失败;
⑵若k=根结点的值,则查找成功;
⑶否则,若k<根结点的值,则在root的左子树上查找;
⑷否则,在root的右子树上查找;
上述过程一直持续到k被找到或者待查找的子树为空,如果待查找的子树为空,则查找失败。
分治法是把一个大问题划分为若干个子问题,分别求解各个子问题,然后再把子问题的解合并得到原问题的解。
减治法同样是把一个大问题划分成若干个子问题,但这些子问题不需要分别求解,只需求解其中一个子问题,因而也无需对子问题的解进行合并。
正是因为少解了很多重复的子问题并且没有了子问题合并的过程,应用减治法处理问题的效率是很高的。
2016年4月11日16时至18时
实验七排序中减治法的程序设计
(1)掌握堆的有关概念
(2)掌握堆排序的基本思想和其算法的实现过程
(3)熟练掌握筛选算法的实现过程
(4)在掌握的基础上编程实现堆排序的具体实现过程
'
给出一个记录序列,用堆排序的方法将其进行升序排列,输出结果,输出时要求有文字说明。
堆排序的基本思想是:
首先将待排序的记录序列构造成一个堆,此时,选出了堆中所有记录的最大者即堆顶记录,然后将它从堆中移走(通常将堆顶记录和堆中最后一个记录交换),并将剩余的记录再调整成堆,这样又找出了次大的记录,以此类推,直到堆中只有一个记录为止。
假设当前要筛选结点的编号为k,堆中最后一个结点的编号为n,并且结点k的左右子树均是堆(即r[k+1]~r[n]满足堆的条件),则筛选算法用伪代码可描述为:
1.设置i和j,分别指向当前要筛选的结点和要筛选结点的左孩子;
2.若结点i已是叶子,则筛选完毕;
否则,比较要筛选结点的左右孩子结点,并将j指向关键码较大的结点;
3.将要筛选结点i的关键码与结点j的关键码进行比较,有以下两种情况:
如果结点i的关键码大,则完全二叉树已经是堆;
否则将r[i]与r[j]交换;
令i=j,转步骤2继续进行筛选;
·
voidvisit(intr[],intn){
10;
i++)
r[i]);
voidSiftHeap(intr[],intk,intn){
inti,j,temp;
i=k;
如何将无序序列调整为堆是堆排序算法的关键,筛选法调整是成功应用减治法的例子。
在堆调整的过程中,总是将根节点(即被调整结点)与左右子树的根节点进行比较,若不满足堆的条件,则将根节点与左右子树中根结点的较大者交换,所以每比较一次,需要调整的完全二叉树的问题规模就减小一半,因此,其时间性能是O(log2n)。
这个自堆顶至叶子的调整过程称为筛选。
实验八淘汰赛冠军问题的程序设计
(2)掌握淘汰赛冠军问题的具体实现过程
(3)通过这个实例进一步掌握递归技术的运用
(4)在掌握的基础上编程实现淘汰赛冠军问题的具体实现过程
假设有n个选手进行竞技淘汰赛,最后决出冠军的选手,请设计竞技淘汰比赛的过程,输出结果,输出时要求有文字说明。
抄书上P90页的想法
intComp(chara,charb){
、
if(a>
b)
在淘汰赛冠军问题中,通过让选手两两竞争的方法,每次比赛可以去掉1/2的选手,减小了子问题的求解次数,节约了时间。
将选手进行分组体现了分治法“分而治之”的思想,让选手通过两两竞争的方法减少比赛的次数的方法体现了减治法的思想。
实验九数塔问题的程序设计
(1)掌握动态规划法的设计思想
(2)掌握数塔问题的具体实现过程
(4)在掌握的基础上编程实现数塔问题的具体实现过程
给出一个数塔,从该数塔的顶层出发,在每一个节点可以选择向左走或向右走,一直走到该数塔的最底层,找出一条路径,使得路径上的数值和最大,输出最大数值及其路径,输出时要求有文字说明。
想法:
1.求解初始子问题:
底层的每个数字可以看作1层数塔,则最大数值和就是其自身;
2.再求解下一阶段的子问题:
第4层的决策是在底层决策的基础上进行求解,可以看作4个2层数塔,对每个数塔进行求解;
3.再求解下一阶段的子问题:
第3层的决策是在第4层决策的基础上进行求解,可以看作3个2层的数塔,对每个数塔进行求解;
4.$
5.以此类推,直到最后一个阶段:
第1层的决策结果就是数塔问题的整体最优解。
【写不下就算了】算法:
1.初始化数组maxAdd的最后一行为数塔的底层数据:
for(j=0;
j<
n;
j++)maxAdd[n-1][j]=d[n-1][j];
2.从第n-1层开始直到第1层对下三角元素maxAdd[i][j]执行下述操作:
maxAdd[i][j]=d[i][j]+max{maxAdd[i+1][j],maxAdd[i+1][j+1]};
如果选择下标j的元素,则path[i][j]=j,否则path[i][j]=j+1;
3.输出最大数值和maxAdd[0][0];
4.根据path数组确定每一层决策的列下标,输出路径信息;
#definen5
voidprintArray(intmaxAdd[n][n],intpath[n][n]){
\nmaxAdd[%d][%d]:
n,n);
for(inti=0;
i<
for(intj=0;
j<
=i;
j++){
maxAdd[i][j]);
}
\npath[%d][%d]:
path[i][j]);
}
intDataTorwer(intd[n][n]){
动态规划法将待求解问题分解成若干个相互重叠的子问题,每个子问题对应决策过程的一个阶段,一般来说,子问题的重叠关系表现在对给定问题求解的递推关系(也就是动态规划函数)中,将子问题的解求解一次并填入表中,当需要再次求解此子问题时,可以通过查表获得该子问题的解而不用再次求解,从而避免了大量重复计算。
2016年4月14日16时至18时
实验十多源点最短路径问题的程序设计
(2)掌握多源点最短路径问题的具体实现过程
(3)通过这个实例进一步掌握动态规划法的运用
(4)在掌握的基础上编程实现多源点最短路径问题的具体实现过程
给定带权有向图G=(V,E),对任意顶点
,求出顶点
的最短路径长度,输出结果,输出时要求有文字说明。
抄书上106页的想法,从设d(vi,vj,V)...一直抄到这就是著名的Floyd算法。
constintMAX=100;
constintn=3;
我理解了用动态规划法求解的问题具有特征:
①能够分解为相互重叠的若干子问题;
②满足最优性原理(也称最优子结构性质):
该问题的最优解中也包含着其子问题的最优解。
实验十一贪心算法解决TSP问题程序设计
(1)掌握贪心法的设计思想
(2)掌握TSP问题的具体实现过程
(4)在掌握的基础上编程实现TSP问题的具体实现过程
给出n个城市及任意两城市间的距离,要求旅行家在旅行这n个城市时,各个城市经历且仅经历一次然后回到出发城市,使得所走的路径最短。
输出结果,输出时要求有文字说明。
最近邻点策略:
从任意城市出发,每次在没有到过的城市中选择最近的一个,直到经过了所有的城市,最后回到出发城市。
设图G有n个顶点,边上的代价存储在二维数组w[n][n]中,集合V存储图的顶点,集合P存储经过的边,最近邻点策略求解TSP问题的算法如下:
1.P={};
2.V=V-{u0};
u=u0;
验过程或源代码
constintn=5;
constintmax=100;
intTSP1(intarc[n][n],intw){
intedgeCount=0,TSPLength=0;
intmin,u,v;
intflag[n]={0};
贪心法在解决问题的策略上目光短浅,只根据当前已有的信息就做出选择,而且一旦做出了选择,不管将来有什么结果,这个选择都不会改变。
换言之,贪心法并不是从整体最优考虑,它所做出的选择只是在某种意义上的局部
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 北大 软件 学院 算法 实验 报告 截图
![提示](https://static.bdocx.com/images/bang_tan.gif)