实验指导书.docx
《实验指导书.docx》由会员分享,可在线阅读,更多相关《实验指导书.docx(30页珍藏版)》请在冰豆网上搜索。
实验指导书
“算法设计与分析”实验指导书目录
“算法设计与分析”实验指导书目录1
实验一集合的表示与操作算法设计2
实验二递归与迭代程序设计3
实验三Kruskal算法的设计5
实验四多段图问题的动态规划算法设计7
实验五检索与周游算法设计9
实验六回溯算法设计11
实验七分支限界算法设计12
实验八游戏中寻址算法的设计14
实验九归并排序的分治策略设计16
实验十哈夫曼编码的贪心算法设计17
实验十一汽车加油算法设计与实现18
实验十二骑士游历算法设计19
实验十三推箱子游戏21
实验十四目录树打印程序的设计22
实验十五多叉路口交通灯的管理问题24
实验十六排课算法的设计与实现26
2.研究NP问题及解决方法;26
5.重新测试用例,执行4;27
1.思考排课是否有其它实现算法,并比较这些算法的性能;27
实验一集合的表示与操作算法设计
[实验目的]
1.了解集合的不同表示方法,掌握集合的树结构表示方法;
2.掌握树结构表示下集合的并运算与查找算法;
3.编程实现集合的表示与操作算法.
[预习要求]
1.认真阅读教材内容,熟悉树结构表示的原理和操作算法;
2.设计和编制实验程序.
[参考数据类型或变量]
typedefElemTypeint/*实型或任意其它元素类型*/
typedefstruct{
ElemTypeelem;
inttag;/*根节点为负的整数,表示该集合的基数的负值,否则为父节点索引指针*/
}NODE;
NODE*set;/*用动态存储分配实现集合的树表示与存储*/
[参考子程序接口与功能描述]
voidInitSet(NODE*set)
功能:
根据集合的基数动态分配存储,输入各元素,初始化子集森林.
intFind(NODE*set,ElemTypeelem)
功能:
在数组set中顺序查找元素elem,如果不成功,返回-1;否则,使用带压缩规则的查找算法,返回所在子集的根节点索引.
intUnion(NODE*set,ElemTypeelem1,ElemTypeelem2)
功能:
应用Find算法首先找到elem1和elem2所在的子集,然后应用带加权规则的并运算算法合并两个子集.不成功时,返回-1;否则,返回并集的根节点索引.
[实验步骤]
1.设计Find的测试方案和程序,输入测试数据,修改并调试程序,直至正确为止;
2.设计Union的测试方案和程序,输入测试数据,修改并调试程序,直至正确为止;
3.待各功能子程序调试完毕,去掉测试程序,将你的程序整理成功能模块存盘备用.
[实验报告要求]
1.阐述实验目的和实验内容;
2.提交实验程序的功能模块;
3.记录最终测试数据和测试结果。
[思考题]
试用C语言实现集合的位向量表示,并设计相应的并、交与查找运算算法.
实验二递归与迭代程序设计
[实验目的]
1.熟悉二分检索问题的线性结构表示和二分检索树表示;
2.熟悉不同存储表示下求解二分检索问题的递归算法设计;
3.通过实例转换,掌握将递归算法转换成迭代算法的方法;
4.掌握应用递归或迭代程序设计实现分治法求解问题的抽象控制策略.
[预习要求]
1.认真阅读算法设计教材和数据结构教材内容,熟悉不同存储表示下求解二分检索问题的原理或方法;
2.针对线性结构表示和二分检索树表示设计递归算法;
3.参考教材和课堂教学内容,根据将递归算法转换成迭代算法的一般步骤将二分检索递归算法转换成相应的迭代算法.
[算法或程序设计参考]
线性结构
intdata[10]={/*10个互异的、无序的原始整数*/};
typedefstruct{ints[100];inttop;}STACK;
intPartition(int*data,intlow,inthigh)
功能:
将data[low,high]进行快速分类划分,返回枢轴记录关键字的位置索引.
intQSort1(int*data,intlow,inthigh)
功能:
将data[low,high]进行快速分类的递归算法.
intQSort2(int*data,intlow,inthigh)
功能:
将data[low,high]进行快速分类的迭代算法.
intBSearch1(int*data,intkey)
功能:
在data数组中检索key的二分检索递归算法,成功时返回位置索引,否则返回-1.
intBSearch2(int*data,intkey)
功能:
在data数组中检索key的二分检索迭代算法,成功时返回位置索引,否则返回-1.
树结构
typedefstructNODE{intkey;structNODE*lch,*rch;}TNODE,*BT;
typedefstructParameters{BT*t;intkey;BTf;BT*p}PARA;
typedefstruct{PARAs[100];inttop;}STACK;
intInsertBT(BT*t,intkey)
功能:
在二分检索树t中插入关键字为key的元素,成功时返回1,否则返回0.
intTSearch1(BT*t,intkey,BTf,BT*p)
功能:
用递归算法在二分检索树t中查找关键字为key的元素,成功时返回1,p指向该元素节点,否则p指向查找路径上最后一个节点并返回0,f指向t的双亲,其初始调用值为NULL.
intTSearch2(BT*t,intkey,BTf,BT*p)
功能:
用迭代算法在二分检索树t中查找关键字为key的元素,成功时返回1,p指向该元素节点,否则p指向查找路径上最后一个节点并返回0,f指向t的双亲,其初始调用值为NULL.
[实验步骤]
1.调试线性结构表示下的快速分类与二分检索递归程序,直至正确为止;
2.调试线性结构表示下的快速分类与二分检索迭代程序,直至正确为止;
3.待各功能子程序调试完毕,去掉测试程序,将程序整理成功能模块存盘备用.
[实验报告要求]
1.阐述实验目的和实验内容;
2.提交实验程序的功能模块;
3.阐述将递归算法改写成迭代算法的一般方法;
4.用类C语言阐述分治法递归与迭代实现抽象控制策略.
[思考与练习]
1.怎样优化由递归程序改写的迭代程序?
2.设计二分检索树的构造与检索递归程序,并将其改写成相应的迭代算法.
实验三Kruskal算法的设计
[实验目的]
1.根据算法设计需要,掌握连通网的灵活表示方法;
2.掌握最小生成树的Kruskal算法;
3.基本掌握贪心算法的一般设计方法;
4.进一步掌握集合的表示与操作算法的应用.
[预习要求]
1.认真阅读算法设计教材和数据结构教材内容,熟习连通网的不同表示方法和最小生成树算法;
2.设计Kruskal算法实验程序.
[参考数据类型或变量]
typedefNodeNumberint;/*节点编号*/
typedefCostTypeint;/*成本值类型*/
typedefElemTypeNodeNumber/*实型或任意其它元素类型*/
typedefstruct{intElemType;inttag;}NODE;
typedefstruct{CostTypecost;NodeNumbernode1,node2;}EDGE;
NODEset[]={{1,-1},…,{n,-1}};/*节点集,n为连通网的节点数*/
EDGEes[]={{valuesofe1},…,{valuesofem}};/*边集,m为连通网的边数*/
EDGEst[n-1];/*最小生成树的边集*/
[参考子程序接口与功能描述]
intFind(NODE*set,ElemTypeelem)
功能:
在数组set中顺序查找元素elem,如果不成功,返回-1;否则,使用带压缩规则的查找算法,返回所在子集的根节点索引.
intUnion(NODE*set,ElemTypeelem1,ElemTypeelem2)
功能:
应用Find算法首先找到elem1和elem2所在的子集,然后应用带加权规则的并运算算法合并两个子集.不成功时,返回-1;否则,返回并集的根节点索引.
voidSort(EDGE*es,intn)
功能:
用任意分类算法将连通图的边集按成本值的非降次序分类.
voidKruskal(EDGE*es,intm,NODE*set,intn,EDGE*st)
功能:
对有n个节点,m条边的连通网,应用Kruskal算法生成最小生成树,最小生成树的边存储在数组st中.
voidOutput(EDGE*st,intn)
功能:
输出最小生成树的各条边.
[实验步骤]
1.设计测试问题,修改并调试程序,输出最小生成树的各条边,直至正确为止;
2.待各功能子程序调试完毕,去掉测试程序,将你的程序整理成功能模块存盘备用.
[实验报告要求]
1.阐述实验目的和实验内容;
2.阐述Kruskal算法的原理方法;
3.提交实验程序的功能模块;
4.提供测试数据和相应的最小生成树.
[思考与练习]
1.设计由连通网初始边集数组生成最小堆的算法;
2.设计输出堆顶元素,并将剩余元素调整成最小堆的算法;
3.针对连通网初始边集最小堆表示,设计Kruskal算法;
4.采用成本邻接矩阵表示连通网时,在剩余边中如何实现最小成本边的查找?
采用成本邻接矩阵表示连通网时,用C语言实现Prim算法.
实验四多段图问题的动态规划算法设计
[实验目的]
1.掌握有向网的成本邻接矩阵表示法;
2.能用程序设计语言实现多段图问题的动态规划递推算法;
3.基本掌握动态规划法的原理方法.
[预习要求]
1.认真阅读数据结构教材和算法设计教材,熟习有向网的成本邻接矩阵表示法和动态规划求解多段图问题的递推原理;
2.设计用动态规划算法求解多段图问题的数据结构和递推程序.
[参考数据类型或变量]
typedefNodeNumberint;/*节点编号*/
typedefCostTypeint;/*成本值类型*/
CostTypecost[n][n]={…};/*成本邻接矩阵,n为顶点数*/
NodeNumberpath[k];/*k段图最短路径上的节点编号数组*/
NodeNumbercur=-1;/*当前邻接节点*/
[参考子程序接口与功能描述]
intFindForward(CostType*cost[n],NodeNumberi,NodeNumbercur)
功能:
根据邻接矩阵查找节点i的下一个前向邻接节点,成功时返回节点编号,否则返回-1;cur为当前的前向邻接节点,第一次调用时其值为-1.
intFindBackward(CostType*cost[n],NodeNumberi,NodeNumbercur)
功能:
根据邻接矩阵查找节点i的下一个后向邻接节点,成功时返回节点编号,否则返回-1;cur为当前的后向邻接节点,第一次调用时其值为-1.
voidFPath(CostType*cost[n],intk,intn,NodeNumber*path)
功能:
n个节点的k段图前向递推算法,path[]存储最短路径节点序列.
voidBPath(CostType*cost[n],intk,intn,NodeNumber*path)
功能:
n个节点的k段图后向递推算法,path[]存储最短路径节点序列.
voidOutPath(intk,NodeNumber*path)
功能:
输出k段图的最短路径序列,path[]存储最短路径节点序列.
[实验步骤]
1.设计程序和测试数据,修改并调试程序,直至正确为止;
2.应用设计的算法和程序输出给定多段图问题的最短路径序列;
3.去掉测试程序,将你的程序整理成功能模块存盘备用.
[实验报告要求]
1.阐述实验目的和实验内容;
2.阐述求解多段图问题的动态规划递推原理;
3.提交实验程序的功能模块;
4.记录最终测试数据和测试结果。
[思考与练习]
试用C语言实现求有向网每对节点之间最短路径的数据结构和动态规划递推算法,要求算法能输出每条最短路径节点序列.
实验五检索与周游算法设计
[实验目的]
1.掌握二元树的不同表示方法(二叉树、邻接矩阵、邻接表);
2.掌握二元树的构造方法;
3.掌握二元树的先根序、中根序、后根序周游算法、宽度优先和深度优先检索算法;
4.进一步熟悉并掌握将递归算法改写成迭代算法的方法。
[预习要求]
1.认真阅读数据结构教材和算法设计教材的相关内容,熟习二元树的二叉树、邻接矩阵和邻接表表示;
2.熟习二元树的先根序、中根序、后根序周游算法和图的宽度优先和深度优先检索算法;
3.针对如图所示的二元树,设计适当的数据结构和算法,编程输出先根序、中根序、后根序周游节点序列和宽度优先、深度优先检索节点序列。
节点中的数据即为节点编号。
[参考数据类型或变量]
typedefstructNode{
intnum;/*节点编号*/
structNode*lch;
structNode*rch;
}*BinTree;
structNeighborhood{
intnum;
structNeighborhood*next;
}*NeighborList[n];/*n个节点的邻接表,动态生成并初始化*/
intNeighborMetrix[n][n]={/*…*/};/*n个节点的邻接矩阵,宜静态初始化*/
[参考子程序接口与功能描述]
BinTreeCreatBinTree(void)
功能:
从键盘输入节点数据,动态生成二叉树,返回生成的二叉树,该二叉树或者为空树,或者为根节点指针。
viodCreatNeighborList(structNeighborhood*NeighborList[],intn)
功能:
从键盘输入节点数据,动态生成并初始化邻接表。
voidPreOrderTraverse(BinTreeT),InOrderTraverse(BinTreeT),PostOrderTraverse(BinTreeT)
功能:
分别按先根序、中根序、后根序周游并输出二元树的节点序列。
voidBFS(structNeighborhood*NeighborList[],intn)
功能:
根据二元树的邻接表表示,按宽度优先检索输出二元树的节点序列。
voidDFS(intNeighborMetrix[][n],intn)
功能:
根据二元树的邻接矩阵表示,按深度优先检索输出二元树的节点序列。
voidDeleteBinTree(BinTreeT)
功能:
释放动态分配的二元树节点空间。
viodDeleteNeighborList(structNeighborhood*NeighborList[],intn)
功能:
释放动态分配的邻接表节点空间。
[实验步骤]
1.录入、修改并调试程序,直至正确为止;
2.按预习要求中提到的实验内容,实录实验的输出结果;
3.将你的程序存盘备用。
[实验报告要求]
1.阐述实验目的和实验内容;
2.提交模块化的实验程序源代码;
3.简述算法和程序的测试过程,提交实验的输出结果;
4.鼓励对实验内容展开讨论,鼓励提交思考与练习题的代码和测试结果。
[思考与练习]
1.试将你的递归算法改写成迭代算法,上机测试正确性。
2.试用不同的方法,设计并实现统计二元树T的叶节点数的算法并分析它的计算时间。
在structNode类型中增加一个指向父节点的指针,设计并实现空间复杂度为O
(1)的二元树周游迭代算法,上机测试正确性。
实验六回溯算法设计
[实验目的]
1.掌握回溯法解题的基本思想;
2.掌握回溯算法的设计方法;
3.针对子集和数问题,熟练掌握回溯递归算法、迭代算法的设计与实现。
[预习要求]
1.认真阅读教材或参考书,掌握回溯法解题的基本思想,算法的抽象控制策略;
2.了解子集和数问题及解向量的定长和变长状态空间表示;
3.针对解向量的定长表示,设计状态空间树节点扩展的规范(限界)函数及实现方法;
4.分析深度优先扩展状态空间树节点或回溯的条件;
5.分析和设计生成解向量各分量可选值的实现方法;
6.设计和编制回溯算法的递归和迭代程序。
[参考数据类型或变量]
floats;//表示有可能抵达答案节点的子路径上的元素之和;
floatr;//尚未测试的剩余集合元素之和;
floatw[n];//存储原始集合的n个元素,根据问题实例初始化;
intx[n];//定长表示的解向量,各元素初始值为0;
[参考子程序接口与功能描述]
voidRecursiveSubset(floats,floatr,intk)
功能:
针对问题实例的递归回溯算法。
voidIterativeSubset(floats,floatr,intk)
功能:
针对问题实例的迭代回溯算法。
voidInitializeInstanse(void)
功能:
问题实例的初始化函数,初始化子集和数M,w,x向量,s,r。
[实验步骤]
1.录入、修改并测试你的程序,直至正确为止;
2.针对问题实例,实录运行时的输入、输出界面;
3.将你的程序和实录的界面存盘备用。
[实验报告要求]
1.阐述实验目的和实验内容;
2.提交模块化的实验程序源代码;
3.简述程序的测试过程,提交实录的输入、输出界面;
4.鼓励对实验内容展开讨论,鼓励提交思考与练习题的代码和测试结果。
[思考与练习]
1.试针对解向量的变长表示设计回溯算法,上机测试正确性。
2.试针对0/1背包问题设计回溯算法,比较与子集和数问题的算法差异。
实验七分支限界算法设计
[实验目的]
1.掌握分支限界法算法的解题的基本思想和设计方法;
2.区分分支限界算法与回溯算法的区别,加深对分支限界法的理解;
3.理解分支限界法算法中的限界函数应遵循正确、准确、高效的设计原则。
[预习要求]
1.认真阅读教材或参考书,掌握分支限界法解题的基本思想;
2.设计状态空间树节点扩展的规范(限界)函数及实现方法;
3.分析和设计生成解向量各分量可选值的实现方法。
[实验内容]
某售货员要到若干城市去推销商品,已知各城市之间的路程(或旅费)。
他要选定一条从驻地出发,经过每个城市一次,最后回到驻地的路线,使总的路程(或总旅费)最小。
[设计提示]
用分支限界求解旅行商问题,其解空间是一个排列树。
有两种基本的实现方法。
第一种是只使用一个优先队列,队列中的每个元素中都包含到达根的路径。
另一种是保留一个部分解空间树和一个优先队列,优先队列中的元素并不包含到达根的路径。
[参考数据类型或变量]
/*定义边结构*/
typedefstruct_EDGE{
inthead;
inttail;
}EDGE;
/*定义路径结构*/
typedefstruct_PATH{
EDGEedge[MAX_CITIES];
intedgesNumber;
}PATH;
/*定义花费矩阵结构*/
typedefstruct_MATRIX{
intdistance[MAX_CITIES][MAX_CITIES];
intcitiesNumber;
}MATRIX;
/*定义树结点*/
typedefstruct_NODE{
intbound;//相应于本结点的花费下界
MATRIXmatrix;//当前花费矩阵
PATHpath;//已经选定的边
struct_NODE*left;//左枝
struct_NODE*right;//右枝
}NODE;
[参考子程序接口与功能描述]
intSimplify(MATRIX*c)
功能:
归约费用矩阵,返回费用矩阵的归约常数
EDGESelectBestEdge(MATRIXc)
功能:
搜索所有花费为零的边中最合适的,使左枝下界更大
MATRIXLeftNode(MATRIXc,EDGEedge)
功能:
删掉所选分枝边
MATRIXRightNode(MATRIXc,EDGEedge,PATHpath)
功能:
删除行列和回路边后的矩阵
EDGELoopEdge(PATHpath,EDGEedge)
功能:
计算回路边的函数,除了加入的新边,当前结点路线集合中还可能包含一些已经选定的边,这些边构成一条或几条路径,为了不构成回路,必须使其中包含新边的路径头尾不能相连,本函数返回这个头尾相连的边,以便把这个回路边的长度设成无穷。
intMatrixSize(MATRIXc,PATHpath)
功能:
计算花费矩阵当前阶数
voidShowPath(PATHpath,MATRIXc)
功能:
显示路径
voidShowMatrix(MATRIXc)
功能:
显示花费矩阵
[实验步骤]
1.录入、修改并测试你的程序,直至正确为止;
2.针对问题实例,实录运行时的输入、输出界面;
3.将你的程序和实录的界面存盘备用。
[实验报告要求]
1.阐述实验目的和实验内容;
2.提交模块化的实验程序源代码;
3.简述程序的测试过程,提交实录的输入、输出界面;
4.鼓励对实验内容展开讨论,鼓励提交思考与练习题的代码和测试结果。
[思考与练习]
1.试针对作业调度问题设计分支限界算法,并上机测试其正确性。
2.试针对本实验中的问题,用回溯解法求解,并比较这两种算法的区别与执行效率。
实验八游戏中寻址算法的设计
[实验目的]
1.掌握树结构和栈的表示及操作方法;
2.熟悉并掌握各类搜索算法的基本思想,如广度优先和深度优先搜索;
3.理解启发式搜索算法(如A*)的应用