实验报告.docx
- 文档编号:12091602
- 上传时间:2023-04-17
- 格式:DOCX
- 页数:31
- 大小:299.75KB
实验报告.docx
《实验报告.docx》由会员分享,可在线阅读,更多相关《实验报告.docx(31页珍藏版)》请在冰豆网上搜索。
实验报告
实验报告
实验一
【实验题目】
约瑟夫环问题
设n个人围坐在一个圆桌周围,现在从第s个人开始报数,数到第m个人,让他出局;然后从出局的下一个人重新开始报数,数到第m个人,再让他出局,……,如此反复直到所有的人全部出局为止。
【实验目的】
掌握线性表不同存储结构以及其对应的算法
【界面设计】
界面代码:
packageJoephus;
importjava.applet.Applet;
importjava.awt.Button;
importjava.awt.Graphics;
importjava.awt.Label;
importjava.awt.TextField;
importjava.awt.event.ActionEvent;
importjava.awt.event.ActionListener;
publicclassJosephusextendsAppletimplementsActionListener
{intn,s,d;
TextFieldt1=newTextField(5);
TextFieldt2=newTextField(5);
TextFieldt3=newTextField(5);
Buttonb1=newButton("确定");
Labelprompt;
publicvoidinit()
{
prompt=newLabel("请输入总人数:
");
add(prompt);add(t1);add(b1);
b1.addActionListener(this);
prompt=newLabel("请输入计数起点:
");
add(prompt);add(t2);add(b1);
b1.addActionListener(this);
prompt=newLabel("请输入间隔数:
");
add(prompt);add(t3);add(b1);
b1.addActionListener(this);
}
publicvoidactionPerformed(ActionEvente)
{
n=Integer.parseInt(t1.getText());
s=Integer.parseInt(t2.getText());
d=Integer.parseInt(t3.getText());
repaint();
}
publicvoidpaint(Graphicsg){
Josephus2JOS=newJosephus2(n);
JOS.display(s,d);
g.drawString(JOS.sq,200,300);
}
}
界面效果:
【算法思想】
由于当某个人退出圆圈后,报数的工作要从下一个人开始继续,剩下的人仍然是围成一个圆圈的,可以使用单向循环链表,由于退出圆圈的工作对应着表中结点的删除操作,对于这种删除操作频繁的情况,选用效率较高的链表结构,为了程序指针每一次都指向一个具体的代表一个人的结点而不需要判断,链表不带头结点。
所以,对于所有人围成的圆圈所对应的数据结构采用一个不带头结点的循环链表来描述。
设头指针为p,并根据具体情况移动。
为了记录退出的人的先后顺序,采用一个顺序表进行存储。
程序结束后再输出依次退出的人的编号顺序。
由于只记录各个结点的number值就可以,所以定义一个字符串。
如:
sq=sq+String.valueOf(q.data)+",";依次输出退出的人的编号。
计数起点,要跳过的个数的流程图
【算法实现】
结点类:
OneLinkNode:
packageJoephus;
/*
结点类
*/
publicclassOneLinkNode
{
publicintdata;
publicOneLinkNodenext;
publicOneLinkNode(intk)
{
data=k;
next=null;
}
publicOneLinkNode()
{
this(0);
}
}
链表类:
OneLink:
packageJoephus;
publicclassOneLink{
//头结点
protectedOneLinkNodehead;
//构造一个空的单向链表
publicOneLink()
{
head=null;
}
//只有一个结点的单向链表
publicOneLink(OneLinkNodeh1)
{
head=h1;
}
//判断链表是否为空
publicbooleanisEmpty()
{
returnhead==null;
}
//用随机数构造n个数的链表
publicOneLink(intn)
{
OneLinkNoderear,q;
if(n>0)
{
intk=(int)(Math.random()*100);
head=newOneLinkNode(k);
rear=head;
for(inti=1;i { k=(int)(Math.random()*100); q=newOneLinkNode(k); rear.next=q; rear=q; } } } } Josephus类: packageJoephus; publicclassJosephus2extendsOneLink{ Stringsq="出列顺序: "; Josephus2()//构造空的单向循环链表 { super(); } Josephus2(intn)//建立n个结点的单向循环链表 {//链表结点值为1到n this(); inti=1; //q新结点,rear尾结点 OneLinkNodeq,rear; if(n>0) { //先创建只有一个结点的单向循环链表 head=newOneLinkNode(i); //指向自己 head.next=head; rear=head; while(i { i++; //新结点 q=newOneLinkNode(i); //新结点的next字段指向head q.next=head; //这里的near是尾结点(第一次就是head)的next字段指向新结点 rear.next=q; //保存新节点的地址,以便下次循环使用 rear=q; } } } //计数起点s,d要跳过的个数 publicvoiddisplay(ints,intd)//解约瑟夫环 { intj=0; OneLinkNodep=head; while(j { j++; p=p.next; } while(p.next! =p)//多于一个结点时循环 { j=0; while(j { j++; p=p.next; } delete(p);//删除p的后继结点 p=p.next; this.output(); } } publicvoiddelete(OneLinkNodep)//删除p的后继结点 { OneLinkNodeq=p.next;//q是p的后继结点 sq=sq+String.valueOf(q.data)+","; if(q==head)//欲删除head指向结点时, head=q.next;//要将head向后移动 p.next=q.next;//删除q } publicvoidoutput()//输出单向链表的各个结点值 { OneLinkNodep=head; do { p=p.next; } while(p! =head); } } [程序调试] 数组实现方法: 数组实现代码: packageshuzu2; importjava.util.Scanner; publicclassJosephus{ privateinttotalperson;//总人数 privateintcount;//要数的数 privateint[]person;//队列 privateint[]out;//出队次序 publicJosephus(){ } publicJosephus(inttotalperson,intcount){ this.totalperson=totalperson; this.count=count; person=newint[totalperson]; for(inti=0;i person[i]=i; } out=newint[totalperson]; } publicvoidrun(){ intcounter=0; inti=0; intj=0; intoutperson=0;//记录已出环人数 while(true){ if(person[i]! =-1){//pserson[i]的值是-1,代表出环 //没有出环,计数器加1 counter++; if((counter)%count==0){ outperson++; out[j++]=i+1; person[i]=-1; } } i=(i+1)%totalperson; if(outperson==totalperson){ //所有的人都出环推出 break; } } System.out.println("出环按顺序为: "); for(intk=0;k //输出出环顺序 System.out.print(out[k]+""); } } publicstaticvoidmain(String[]args){ intm=0; intn=0; Scannerscn=newScanner(System.in); while(true){ System.out.println("请输入约瑟夫环的总人数: "); m=scn.nextInt(); System.out.println("请输入要数的数! "); n=scn.nextInt(); if(m! =0&&n! =0){ Josephusyu=newJosephus(m,n); yu.run(); break; }else{ System.out.println("您输入的数据有错误,请重试! "); } } } } 【难点总结】 因为约瑟夫环问题是一个经典的数据结构问题,资料很丰富,查阅了一些资料,对各种语言各种方法解决这一问题都有一定程度掌握。 但在实现界面效果时,开始不会做,多看了几本书,慢慢摸索找到了解决办法。 界面效果只实现了链表方式的,数组方式的没有实现界面效果。 请老师多多指教! 实验二 【实验题目】 对称二叉树 对称二叉树指二叉树的左右子树的结构是对称的。 生成一棵二叉树(二叉树链表)。 判断该二叉树是否为对称二叉树。 计算该二叉树的叶子数 【实验目的】 熟练掌握二叉树的存储及操作 【界面设计】 界面代码: packageTree; importjava.applet.Applet; importjava.awt.*; importjava.awt.event.ActionEvent; importjava.awt.event.ActionListener; importjava.awt.image.ImageProducer; import.URL; importjavax.swing.JTextArea; publicclassTesttreeextendsApplet{ JTextAreaview=newJTextArea("该树的叶子数为: ");//显示的文本域 publicvoidinit() { add(view);} publicvoidpaint(Graphicsg){ Treenewtree=newTree(); newtree.preorder(newtree.head); view.append(String.valueOf(newtree.n)); } } 界面效果: 【算法思想】 生成一棵树(二叉链表)并判断该树是否为对称二叉树。 (提示: 判断二叉树是否对称事实上是其左右子树是否对称同构的判断。 而对左右子树是否对称同构的判断又依赖于左子树的左右子树分别和右子树的右左子树是否对称的判断。 提示可先设计一个算法用来判断两个二叉树是否同构对称。 可用递归法。 【流程图】 【算法实现】 逻辑: packageTree; publicclassTree{ //构造一棵树,用链表保存结构 Nodehead,p2,p3,p4,p5,p6,p7;//树结点 publicTree(){ head=newNode (1); p2=newNode (2); p3=newNode(3); p4=newNode(4); p5=newNode(5); p6=newNode(6); p7=newNode(7); //结点之间关系 head.Lchild=p2; head.Rchild=p3; p2.Rchild=p4; p3.Lchild=p5; p4.Lchild=p6; p4.Rchild=p7; } intn=0;//用于统计叶子数的变量 //先序遍历统计叶子 publicvoidpreorder(Nodee){ //如果还有左孩子,递归遍历左孩子 if(e.Lchild! =null){ preorder(e.Lchild); } //如果还有右孩子,递归遍历右孩子 if(e.Rchild! =null){ preorder(e.Rchild); } //如果左右孩子都没有了,则是叶子结点,计数加1 if(e.Lchild==null&&e.Rchild==null){ n++; } } } //结点类 classNode{ intdata; NodeLchild; NodeRchild; //给出数据,构造节点,数据域表示编号,两个指针分别指向左右孩子 publicNode(inte){ data=e; Lchild=null; Rchild=null; } } 【难点总结】 二叉树的实验刚开始无从下手,资料也比较少,但经过同学们的讲解后,我才明白如何用代码实现,而不止停留在原来的理论上。 实验三 【实验题目】 魔方阵问题 指方阵的每一行、每一列和对角线之和均相等。 要求打印n(n为奇数)阶方阵。 【实验目的】 熟悉二维数组的使用 【界面设计】 【算法思想】 奇次魔方阵实现规则可以描述如下: (1)首先将1填在方阵第一行的中间,即(1,(n+1)/2)的位置; (2)下一个数填在上一个数的主对角线的上方,若上一个数的位置是(i,j),下一个数应填在(i1,j1),其中i1=i-1、j1=j-1。 (3)若应填写的位置下标出界,则出界的值用n来替代;即若i-1=0,则取i1=n;若j-1=0,则取j1=n。 (4)若应填的位置虽然没有出界,但是已经填有数据的话,则应填在上一个数的下面(行减1,列不变),即取i1=i-1,j1=j。 这样循环填数,直到把n*n个数全部填入方阵中,最后得到的是一个n阶魔方阵。 【算法实现】 packageMagic_phalanx; importjava.awt.*; importjava.applet.*; importjava.awt.event.*; publicclassMagic_phalanxextendsAppletimplementsActionListener {intm; TextFieldt1=newTextField(5); Buttonb1=newButton("确定"); Labelprompt; publicvoidinit() { prompt=newLabel("请输入不小于3的正奇数: "); add(prompt);add(t1);add(b1); b1.addActionListener(this); } publicvoidactionPerformed(ActionEvente) { m=Integer.parseInt(t1.getText()); repaint(); } publicvoidpaint(Graphicsg) { inta[][]=newint[m+1][m+1]; inti,j,k,r=0; //初始化 for(i=1;i<=m;i++) for(j=1;j<=m;j++) a[i][j]=0; //创建魔方阵 j=(m+1)/2; a[1][j]=1; for(k=2;k<=m*m;k++) { i--; j++; if((i<1)&&(j>m)) { i+=2; j--; } else { if(i<1)i=m; if(j>m)j=1; } if(a[i][j]==0)a[i][j]=k; else { i+=2; j--; a[i][j]=k; } } //输出 if(m%2==0) { g.drawString("请输入一个1-20之间的奇数! ",300,200); } else {if(m>=1&&m<20) { for(i=1;i<=m;i++) { for(j=1;j<=m;j++) { g.drawString(String.valueOf(a[i][j]),(r%m)*40+20,(r/m)*30+80);//输出魔方,每隔m个数换行 r++; } } } else {g.drawString("请输入一个1-20之间的奇数! ",300,200); } } } } [程序调试] 【难点总结】 魔方问题是我最感兴趣的实验题,我是最先做好,并做好了它的界面效果,这为后几个实验的界面效果的实现铺平了道路。 魔方的算法虽然很明白,但开始对java语言不是很精通,遇到了很多问题,同时走了很多弯路。 这些困难,都在不断的查阅资料,不断向其他同学和学长讨教后解决了。 实验四 【实验题目】 地图四染色问题 “四染色”定理是计算机科学中著名的定理之一。 使地图中相邻的国家或行政区域不重色,最少可用四种颜色对地图着色。 证明此定理的结论,利用栈采用回溯法对地图着色。 【实验目的】 熟悉图的存储结构及操作。 理解回溯算法思想。 【界面设计】 界面代码: packagemap; importjava.applet.Applet; import.URL; importjava.awt.*; importjava.awt.event.ActionEvent; importjava.awt.event.ActionListener; importjava.awt.image.ImageProducer; importjavax.swing.JTextArea; publicclassTestmapextendsApplet{ JTextAreaview=newJTextArea("填色结果如下: ");//显示的文本 Imageim; publicvoidinit() { URLurl=getClass().getResource("map.jpg"); try{ im=createImage((ImageProducer)url.getContent()); if(im==null){ System.out.println("nullimage"); } } catch(Exceptione){ e.printStackTrace(); } add(view); } publicvoidpaint(Graphicsg){ mapnewmap=newmap(); for(inti=0;i<7;i++){ view.append("\n"); view.append(newmap.mapcolor[i]); Insetsinsets=getInsets(); g.drawImage(im,insets.left,insets.top,this);} } publicvoidupdate(Graphicsg){ paint(g); } } 界面效果: 【算法思想】 对每个行政区编号: 1-7,对颜色编号: a、b、c、d;从第一号行政区开始逐一染色,每一个区域逐次用四种颜色进行试探,若所取颜色与周围不重,则用栈记下来该区域的色数,否则依次用下一色数进行试探。 若出现a-d均与周围发生重色,则需退栈回溯,修改当前栈顶的色数。 【算法实现】 packagemap; publicclassmap{ Stringma
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验 报告