西安交通大学数据结构课外实验报告.docx
- 文档编号:11802127
- 上传时间:2023-04-02
- 格式:DOCX
- 页数:18
- 大小:71.26KB
西安交通大学数据结构课外实验报告.docx
《西安交通大学数据结构课外实验报告.docx》由会员分享,可在线阅读,更多相关《西安交通大学数据结构课外实验报告.docx(18页珍藏版)》请在冰豆网上搜索。
西安交通大学数据结构课外实验报告
数据结构课外实验报告
1背包问题
1.1问题描述
假设有一个能装入总体积为T的背包和n件体积分别为w1,w2,…wn的物品,能否从n件物品中挑选若干件恰好装满背包,即使w1+w2+…+wm=T,要求找出所有满足上述条件的解。
例如:
当T=10,各件物品的体积{1,8,4,3,5,2}时,可找到下列4组解:
(1,4,3,2)
(1,4,5)
(8,2)
(3,5,2)
1.2算法设计
利用回溯法的设计思想来解决背包问题。
首先,将物品排成一列,然后,顺序选取物品装入背包,若已选取第i件物品后未满,则继续选取第i+1件,若该件物品“太大”不能装入,则弃之,继续选取下一件,直至背包装满为止。
如果在剩余的物品中找不到合适的物品以填满背包,则说明“刚刚”装入的物品“不合适”,应将它取出“弃之一边”,继续再从“它之后”的物品中选取,如此重复,直到求得满足条件的解,或者无解。
由于回溯求解的规则是“后进先出”,自然要用到“栈”。
同时,因为要使用回溯法,所以采取一个data数组来记录入栈的数据在原本的数组中的位置信息,从而可以保证回溯时回溯到恰当的位置之上。
1.3源代码
//beibao.cpp:
定义控制台应用程序的入口点。
#include"stdafx.h"
#include
#definesize20
usingnamespacestd;
classstacks
{
public:
intdata[size];
inttop;
}stack;
intmain()
{
intw[size];
intv;
intk=0;
intj=1;
intnumber;
ints=0;
cout<<"pleaseinputthenumberoftheobjects:
"< cin>>number; cout<<"pleaseinputthevolumeoftheobjects: "< for(inti=0;i { cin>>w[i]; s=s+w[i]; } cout<<"pleaseinputthelimitofthevolume: "< cin>>v; if(v<0||v>s) cout<<"wrong"< for(inti=0;i stack.data[i]=0; stack.top=0; do { while(v>0&&k { if(v>=w[k]) { stack.data[stack.top]=k; stack.top++; v-=w[k]; } k++; } if(v==0) { cout<<"the"< "< for(inti=0;i { cout< } j++; cout< } --stack.top; k=stack.data[stack.top]; stack.data[stack.top]=0; v+=w[k]; k++; } while(! (stack.top==0&&k==number)); getchar(); return0; } 1.4运行结果 2农夫过河问题 2.1问题描述 一个农夫带着一只狼、一只羊和一棵白菜,身处河的南岸。 他要把这些东西全部运到北岸。 他面前只有一条小船,船只能容下他和一件物品,另外只有农夫才能撑船。 如果农夫在场,则狼不能吃羊,羊不能吃白菜,否则狼会吃羊,羊会吃白菜,所以农夫不能留下羊和白菜自己离开,也不能留下狼和羊自己离开,而狼不吃白菜。 请求出农夫将所有的东西运过河的方案。 2.2算法设计 求解这个问题的简单方法是一步一步进行试探,每一步搜索所有可能的选择,对前一步合适的选择后再考虑下一步的各种方案。 要模拟农夫过河问题,首先需要对问题中的每个角色的位置进行描述。 可用4位二进制数顺序分别表示农夫、狼、白菜和羊的位置。 用0表在南岸,1表示在北岸。 例如,整数5(0101)表示农夫和白菜在南岸,而狼和羊在北岸。 现在问题变成: 从初始的状态二进制0000(全部在河的南岸)出发,寻找一种全部由安全状态构成的状态序列,它以二进制1111(全部到达河的北岸)为最终目标。 总状态共16种(0000到1111),(或者看成16个顶点的有向图)可采用广度优先或深度优先的搜索策略---得到从0000到1111的安全路径。 首先用一个函数来保证这16种状态之中是否是安全的,可以知道,其中的十种情况是安全的,将其记录下来。 然后,再设计另一个函数,来判断其中的两种状态是否可以在一步中完成,如果可以返回1,不可以返回0。 就可以通过这样的方式建立一个十乘十的邻接矩阵,如果两种状态可以一步完成,那么就在邻接矩阵中的恰当位置添上1,否则不变,仍旧为0。 最后,用两种方式来搜索路径,从而得到两种结果。 2.3源代码 //farmer.cpp: 定义控制台应用程序的入口点。 #include"stdafx.h" #include #include #defineVEX_NUM10 usingnamespacestd; typedefstruct { intFarmer,Wolf,Sheep,Veget; }VexType; typedefstruct { intvexnum,e; VexTypevexs[VEX_NUM]; intadj[VEX_NUM][VEX_NUM]; }AdjGraph; intvisited[VEX_NUM]; intpath[VEX_NUM]; intsafe(intF,intW,intS,intV) { if(F! =S&&(W==S||S==V)) return0; else return1; } intconnected(AdjGraph&G,inti,intj) { intk; k=0; if(G.vexs[i].Wolf! =G.vexs[j].Wolf) k++; if(G.vexs[i].Sheep! =G.vexs[j].Sheep) k++; if(G.vexs[i].Veget! =G.vexs[j].Veget) k++; if(G.vexs[i].Farmer! =G.vexs[j].Farmer&&k<=1) return1; else return0; } intlocate(AdjGraph&G,intF,intW,intS,intV) { inti; for(i=0;i if(G.vexs[i].Farmer==F&&G.vexs[i].Wolf==W&&G.vexs[i].Sheep==S&&G.vexs[i].Veget==V) returni; return-1; } voidCreate(AdjGraph&G) { inti,j,F,W,S,V; i=0; for(F=0;F<=1;F++) for(W=0;W<=1;W++) for(S=0;S<=1;S++) for(V=0;V<=1;V++) if(safe(F,W,S,V)==1) { G.vexs[i].Farmer=F; G.vexs[i].Wolf=W; G.vexs[i].Sheep=S; G.vexs[i].Veget=V; i++; } G.vexnum=i; for(i=0;i for(j=0;j if(connected(G,i,j)==1) G.adj[i][j]=G.adj[i][j]=1; else G.adj[i][j]=G.adj[j][i]=0; return; } voidprintpath(AdjGraph&G,intu,intv) { intk=u; while(k! =v) { printf("(%d,%d,%d,%d)\n",G.vexs[k].Farmer,G.vexs[k].Wolf,G.vexs[k].Sheep,G.vexs[k].Veget); k=path[k]; } printf("(%d,%d,%d,%d)\n",G.vexs[k].Farmer,G.vexs[k].Wolf,G.vexs[k].Sheep,G.vexs[k].Veget); } voidDFSpath(AdjGraph&G,intu,intv) { intob; visited[u]=1; for(ob=0;ob if(G.adj[u][ob]==1&&visited[ob]==0&&visited[v]==0) { path[u]=ob; DFSpath(G,ob,v); } } voidDFSpath2(AdjGraph&G,intu,intv) { intob; visited[u]=1; for(ob=G.vexnum-1;ob>=0;ob--) if(G.adj[u][ob]==1&&visited[ob]==0&&visited[v]==0) { path[u]=ob; DFSpath2(G,ob,v); } } voidmain() { inti,j; AdjGraphgraph1; Create(graph1); for(i=0;i visited[i]=0; i=locate(graph1,0,0,0,0); j=locate(graph1,1,1,1,1); DFSpath(graph1,i,j); if(visited[j]==1) { printf("0代表南岸,1代表北岸\n四个整数依次代表\n(农夫狼羊白菜)\n"); printpath(graph1,i,j); } for(i=0;i visited[i]=0; for(i=0;i path[i]=0; AdjGraphgraph2; Create(graph2); i=locate(graph2,0,0,0,0); j=locate(graph2,1,1,1,1); DFSpath2(graph2,i,j); if(visited[j]==1) { printf("0代表南岸,1代表北岸\n四个整数依次代表\n(农夫狼羊白菜)\n"); printpath(graph2,i,j); } getchar(); return; } 2.4运行结果 3八皇后问题 3.1问题描述 设在初始状态下在国际象棋的棋盘上没有任何棋子(这里的棋子指皇后棋子)。 然后顺序在第1行,第2行……第8行上布放棋子。 在每一行中共有8个可选择的位置,但在任一时刻棋盘的合法布局都必须满足3个限制条件 (1)任意两个棋子不得放在同一行 (2)任意两个棋子不得放在同一列上(3)任意棋子不得放在同一正斜线和反斜线上。 3.2算法设计 在第i行布放棋子时,从第1列到第8列逐列考察。 当在第i行第j列布放棋子时,需要考察布放棋子后在行方向、列方向、正斜线和反斜线方向上的布局状态是否合法,若该棋子布放合法,再递归求解在第i+1行布放棋子;若该棋子布放不合法,移去这个棋子,恢复布放该棋子前的状态,然后再试探在第i行第j+1列布放棋子。 用不同的数组来表示正斜线,负斜线,横线,竖线上是否是安全状态。 3.3源代码 //queens.cpp: 定义控制台应用程序的入口点。 #include"stdafx.h" #include usingnamespacestd; intdata[8][8]; inta[8]; intb[15]; intc[15]; intnumber=0; voideightQueens(int); voidoutput(constint[][8],int); intmain() { inti,j; for(i=0;i<15;++i) b[i]=c[i]=0; for(i=0;i<8;++i) { a[i]=0; for(j=0;j<8;++j) data[i][j]=0; } eightQueens(0); cout<<"/ncount="< return0; } voideightQueens(intline) { if(line==8) { output(data,8); cout< return; } for(intcolumn=0;column<8;++column) { if(a[column]==0&&b[line-column+7]==0&&c[line+column]==0) { data[line][column]=1; a[column]=1; b[line-column+7]=1; c[line+column]=1; eightQueens(line+1); data[line][column]=0; a[column]=0; b[line-column+7]=0; c[line+column]=0; } } } voidoutput(constintdata[][8],intsize) { for(inti=0;i { for(intj=0;j cout< cout< } ++number; getchar(); } 3.4运行结果 4二叉排序树 4.1问题描述 分别采用二叉链表和顺序表作存储结构,实现对二叉排序树的操作。 用二叉链表作存储结构实现二叉排序树。 1)以回车符(‘\n’)为输入结束标志,输入数列L,生成一棵二叉排序树T; 2)对二叉排序树T作中序遍历,输出结果; 3)计算二叉排序树T查找成功的平均查找长度,输出结果; 4)输入元素x,查找二叉排序树T,若存在含x的结点,则删除该结点,并作中序遍历(执行操作2);否则,输出信息“无x”; 4.2算法设计 按照二叉排序树的规则来对元素进行插入的操作,小于向左,大于向右。 用deep这个量,来记录下每个结点的高度。 所有结点的高度之和,取平均数,就可以得到平均的查找长度。 输出结果的顺序由中序遍历实现。 4.3源代码 //chazhao.cpp: 定义控制台应用程序的入口点。 #include"stdafx.h" #include intdeep=1; usingnamespacestd; classnode { public: node(inti): data(i),left(NULL),right(NULL){} voidinorder(node*&root) { if(root! =NULL) { inorder(root->left); cout< inorder(root->right); } } voidinsert(node*&ptr,intitem) { if(ptr==NULL) { deep++; ptr=newnode(item); } elseif(item { deep++; insert(ptr->left,item); } else { deep++; insert(ptr->right,item); } } node*find(node*&ptr,intitem) { if(ptr==NULL) returnNULL; if(ptr->data==item) returnptr; elseif(item find(ptr->left,item); elsefind(ptr->right,item); } node*&findy(node*&ptr,intitem) { if(ptr->data==item) returnptr; elseif(item findy(ptr->left,item); elsefindy(ptr->right,item); } node*rl() { returnleft; } node*rr() { returnright; } voiddele(node*&ptr) { if(ptr->rl()==NULL&&ptr->rr()==NULL) ptr=NULL; elseif(ptr->rr()==NULL) ptr=ptr->rl(); else ptr=ptr->rr(); } private: intdata; node*left; node*right; }; intmain() { intt,i=0,j; floatresult=0; cout<<"pleaseinputthenumberofthearray: "; cin>>t; cout<<"pleaseinput"< "; cin>>j; node*x=newnode(j); for(;i { cin>>j; x->insert(x,j); } cout<<"theresultofinorderingis: "; x->inorder(x); cout<<"\ntheaveragelengthofinordering: "< result=(float)deep/(float)t; cout< cout<<"\npleaseinputthenumberwhichshouldbeoperated: "< cin>>j; while(j! =-1) { node*t=x->find(x,j); if(t! =NULL) { node*&y=x->findy(x,j); x->dele(y); cout<<"theresultofinorderingis: "; x->inorder(x); } else cout<<"no"< cout<<"\npleaseinputthenumberwhichshouldbeoperated: "< cin>>j; } return0; } 4.4运行结果 5心得 本实验实现了数据结构中三大结构的应用,并且将其运用于较为实际的问题之中。 第一题中采用的是栈,背包问题用栈实现可以很好地完成背包物品的放入和拿出的操作。 第二题中采用的结构是图,将农夫、狼、羊和白菜四个物品在南北岸的几种安全状态来看作图的顶点,如果能够一步完成则看作为这两个点之间有连线,最后就可以找到合理的过河方式。 第三题主要用的是数组,用数组来保证安全与不安全,只要在适当的地方填上零一数字,就可以完成题目要求。 第四题中,使用的是三大结构中的最后一个结构,树。 二叉排序树有着其独特的特点,可以通过其特定的形态来做到具体的实现。 由此次实验,数据结构理论上的东西得到了实现,理论的知识有了实际的意义。 同时,也知道了数据结构的重要性,以及在课上学习内容的不够。 所以,虽然说数据结构已经结课,但是还是需要更加深入的继续学习才行。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 西安交通大学 数据结构 课外 实验 报告