数据结构与算法分析专题实验西安交大赵仲孟.docx

上传人:b****7 文档编号:23315464 上传时间:2023-05-16 格式:DOCX 页数:35 大小:122.38KB
下载 相关 举报
数据结构与算法分析专题实验西安交大赵仲孟.docx_第1页
第1页 / 共35页
数据结构与算法分析专题实验西安交大赵仲孟.docx_第2页
第2页 / 共35页
数据结构与算法分析专题实验西安交大赵仲孟.docx_第3页
第3页 / 共35页
数据结构与算法分析专题实验西安交大赵仲孟.docx_第4页
第4页 / 共35页
数据结构与算法分析专题实验西安交大赵仲孟.docx_第5页
第5页 / 共35页
点击查看更多>>
下载资源
资源描述

数据结构与算法分析专题实验西安交大赵仲孟.docx

《数据结构与算法分析专题实验西安交大赵仲孟.docx》由会员分享,可在线阅读,更多相关《数据结构与算法分析专题实验西安交大赵仲孟.docx(35页珍藏版)》请在冰豆网上搜索。

数据结构与算法分析专题实验西安交大赵仲孟.docx

数据结构与算法分析专题实验西安交大赵仲孟

西安交通大学

数据结构与算法课程实验

实验名称:

数据结构与算法课程专题实验

所属学院:

电信学院

专业班级:

计算机32班

小组成员:

指导老师:

赵仲孟教授

实验一背包问题的求解

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)。

2.实现提示

可利用回溯法的设计思想来解决背包问题。

首先,将物品排成一列,然后,顺序选取物品装入背包,若已选取第i件物品后未满,则继续选取第i+1件,若该件物品“太大”不能装入,则弃之,继续选取下一件,直至背包装满为止。

如果在剩余的物品中找不到合适的物品以填满背包,则说明“刚刚”装入的物品“不合适”,应将它取出“弃之一边”,继续再从“它之后”的物品中选取,如此重复,直到求得满足条件的解,或者无解。

由于回溯求解的规则是“后进先出”,自然要用到“栈”。

3.问题分析

1、设计基础            

后进先出,用到栈结构。

 

2、分析设计课题的要求,要求编程实现以下功能:

        

a.从n件物品中挑选若干件恰好装满背包 

b.要求找出所有满足上述条件的解,例如:

当T=10,各件物品的体积{1,8,4,

3,5,2}时,可找到下列4组解:

(1,4,3,2)、(1,4,5)、(8,2)、(3,5,2)

3,要使物品价值最高,即p1*x1+p2*x1+...+pi*xi(其1<=i<=n,x取0或1,取1表示选取物品i) 取得最大值。

 在该问题中需要决定x1 .. xn的值。

假设按i = 1,2,...,n 的次序来确定xi 的值。

如果置x1 = 0,则问题转变为相对于其余物品(即物品2,3,.,n),背包容量仍为c 的背包问题。

若置x1 = 1,问题就变为关于最大背包容量为c-w1 的问题。

现设r={c,c-w1} 为剩余的背包容量。

在第一次决策之后,剩下的问题便是考虑背包容量为r 时的决策。

不管x1 是0或是1,[x2 ,.,xn ] 必须是第一次决策之后的一个最优方案。

也就是说在此问题中,最优决策序列由最优决策子序列组成。

这样就满足了动态规划的程序设计条件。

4.问题实现

代码1:

#include"iostream"

usingnamespacestd;

classLink{

public:

intm;

Link*next;

Link(inta=0,Link*b=NULL){

m=a;

next=b;

}

};

classLStack{

private:

Link*top;

intsize;

inta[100];

public:

LStack(intsz=0){

top=NULL;

size=0;

a[0]=0;

}

~LStack(){

clear();

}

voidclear(){

while(top!

=NULL){

Link*temp=top;

top=top->next;

deletetemp;

}

size=0;

}

voidpush(intit,intb){

top=newLink(it,top);

a[size]=b;

size++;

}

intpop(){

intit=top->m;

Link*ltemp=top->next;

deletetop;

top=ltemp;

size--;

returnit;

}

inttopValue(){

returntop->m;

}

intlength(){

returnsize;

}

intsum(){

ints=0;

for(inti=0;i

s=s+a[i];

returns;

}

voidprint(){

for(inti=0;i

cout<

cout<

}

};

voidpanduan(intx1,intn,intx2[],LStack*x4){

inti,ss=0;

for(i=x4->pop()+1;i

if(x4->sum()+x2[i]<=x1)

{

x4->push(i,x2[i]);

}

if(x4->sum()==x1)

{

x4->print();

break;

}

}

if(x4->length()==1&&x4->topValue()==n-1)

return;

elsepanduan(x1,n,x2,x4);

}

intmain(){

LStack*ll=newLStack(0);

intm[100];

intn,z;

cout<<"输入物品个数"<

cin>>n;

cout<<"输入物品大小"<

for(inti=0;i

cin>>m[i];

cout<<"输入背包大小"<

cin>>z;

ll->push(-1,0);

cout<<"符合条件的解"<

panduan(z,n,m,ll);

return0;

}

结果1:

代码2:

#include

#include

usingnamespacestd;

structBag

{

intV;//背包体积

intnumber;//物品数量

intv[20];//物品体积

intvalue[20];//物品价值

intdp[20][20];//最大价值

}bag;

intmax(inta,intb)

{

returna>b?

a:

b;

}

intmain()

{

cout<<"请输入背包的容量:

"<

cin>>bag.V;

cout<<"请输入物品的数量:

"<

cin>>bag.number;

cout<<"请输入每件物品的体积:

"<

for(inti=1;i<=bag.number;i++)

{

cin>>bag.v[i];

}

cout<<"请输入每件物品的价值:

"<

for(inti=1;i<=bag.number;i++)

{

cin>>bag.value[i];

}

memset(bag.dp,0,sizeof(bag.dp));//dp中的每一个元素置零

for(inti=1;i<=bag.number;i++)

for(intj=0;j<=bag.V;j++)

{

if(j>=bag.v[i])

bag.dp[i][j]=max(bag.dp[i-1][j],bag.dp[i-1][j-bag.v[i]]+bag.value[i]);

else

bag.dp[i][j]=bag.dp[i-1][j];

}

cout<<"最大价值:

"<

return0;

}

结果2:

熟悉了堆栈的使用,设用数组weight[1..N]存放物品重量,MaxW表示背包的最大装载量。

每进栈一个物品,就从sum中减去该物品的质量,设i为待选物品序号,若

sum-weight[i]>=0,则该物品可选;若sum-weight[i] < 0,则该物品不可选,且若i>n,则需退栈,若此时栈空,则说明无解。

实验二二叉排序树的实现

1.问题描述

分别采用二叉链表和顺序表作存储结构,实现对二叉排序树的操作。

2.基本要求(选择其中之一方式实现)

(1)用二叉链表作存储结构实现二叉排序树。

(2)以回车符(‘\n’)为输入结束标志,输入数列L,生成一棵二叉排序树T;

(3)对二叉排序树T作中序遍历,输出结果;

(4)计算二叉排序树T查找成功的平均查找长度,输出结果;

(5)输入元素x,查找二叉排序树T,若存在含x的结点,则删除该结点,并作中序遍历(执行操作2);否则,输出信息“无x”;

3.问题分析

可以再二叉树建立时记录每个节点移动到正确位置所需要的移动步数,再用总的移动步数除以总的节点数就是平均查找步数。

4.算法实现

代码:

#include"iostream"

#include"math.h"

#include"string.h"

#include"stdlib.h"

usingnamespacestd;

classBSTNode{

public:

doubleit;

BSTNode*lc;

BSTNode*rc;

BSTNode(){

lc=rc=NULL;

}

BSTNode(doublea,BSTNode*l=NULL,BSTNode*r=NULL){

it=a;

lc=l;

rc=r;

}

~BSTNode(){}

doublegetele(){

returnit;

}

voidsetele(doublea){

it=a;

}

inlineBSTNode*getlc(){

returnlc;

}

inlineBSTNode*getrc(){

returnrc;

}

inlinevoidsetlc(BSTNode*a){

lc=a;

}

inlinevoidsetrc(BSTNode*a){

rc=a;

}

boolisleaf(){

return(lc==NULL&&rc==NULL);

}

};

classBST{

friendclassBSTNode;

private:

BSTNode*root;

intnodecount;

intcd;

voidclearhelp(BSTNode*);

boolfindhelp(BSTNode*,double);

BSTNode*getmin(BSTNode*);

BSTNode*deletemin(BSTNode*);

BSTNode*insethelp(BSTNode*,double);

BSTNode*removehelp(BSTNode*,double);

voidprinthelp(BSTNode*,int);

public:

BST(){

root=NULL;

nodecount=0;

cd=0;

}

~BST(){

clearhelp(root);

}

voidclear(){

clearhelp(root);

nodecount=0;

}

voidinset(doublea){

root=insethelp(root,a);

}

doubleremove(doublea){

if(findhelp(root,a)){

root=removehelp(root,a);

nodecount--;

cd--;

}

else

cout<<"无"<

}

voidprint(){

if(root==NULL)

cout<<"Treeisempty"<

else

printhelp(root,0);

}

voidchazhaochangdu(){

inta;

a=cd/nodecount;

cout<

}

};

boolBST:

:

findhelp(BSTNode*root,doublea){

if(root==NULL)

returnfalse;

if(ait)

returnfindhelp(root->lc,a);

elseif(a>root->it)

returnfindhelp(root->rc,a);

elseif(a==root->it)

returntrue;

}

BSTNode*BST:

:

insethelp(BSTNode*root,doublea){

if(root==NULL)

{cd++;

nodecount++;

returnnewBSTNode(a,NULL,NULL);

}

if(a<=root->it)

{cd++;

root->setlc(insethelp(root->lc,a));

}

elseif(a>root->it)

{cd++;

root->setrc(insethelp(root->rc,a));

}

returnroot;

}

BSTNode*BST:

:

deletemin(BSTNode*rt){

if(rt->lc==NULL)

returnrt->rc;

else{

rt->setlc(deletemin(rt->lc));

returnrt;

}

}

BSTNode*BST:

:

getmin(BSTNode*rt){

if(rt->lc==NULL)

returnrt;

elsereturngetmin(rt->lc);

}

BSTNode*BST:

:

removehelp(BSTNode*rt,doublea){

if(rt==NULL)returnNULL;

elseif(ait)

rt->setlc(removehelp(rt->lc,a));

elseif(a>rt->it)

rt->setrc(removehelp(rt->rc,a));

else{

BSTNode*temp=rt;

if(rt->lc==NULL){

rt=rt->rc;

deletetemp;

}

elseif(rt->rc==NULL){

rt=rt->lc;

deletetemp;

}

else{

BSTNode*temp=getmin(rt->rc);

rt->it=temp->it;

rt->setrc(deletemin(rt->rc));

deletetemp;

}

}

returnrt;

}

voidBST:

:

clearhelp(BSTNode*root){

if(root==NULL)return;

clearhelp(root->lc);

clearhelp(root->rc);

deleteroot;

}

voidBST:

:

printhelp(BSTNode*root,intlevel){

if(root==NULL)return;

printhelp(root->lc,level+1);

cout<it<<"";

printhelp(root->rc,level+1);

}

intmain(){

BSTa;

stringb;

inti;

cout<<"输入数据以\\n结束"<

for(;;){

cin>>b;

if(b.at(0)=='\\'){

break;

}

else{

a.inset(atof(b.c_str()));

}

}

a.print();

cout<

a.chazhaochangdu();

for(;;){

cout<<"输入要删除的数"<

doublex;

cin>>x;

a.remove(x);

a.print();

}

return0;

}

结果:

实验三约瑟夫环

1.问题描述

设编号为1,2,…,n(n>0)个人按顺时针方向围坐一圈,每人持有一个正整数密码。

开始时任意给出一个报数上限m,从第一个人开始顺时针方向自1起顺序报数,报到m时停止报数,报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人起重新自1报数;如此下去直到所有人全部出列为止

2.基本要求

设计一个程序模拟此过程,给出出列人的编号序列。

3、实现提示:

程序运行之后,首先要求用户指定初始报数的上限值,此题中循环链表可以不设头结点,而且必须注意空表和“非空表”的界限。

如N=20时,若从第一人开始,设每个人的编号依次是1,2,3,……..开始报数,报到20的人出列。

代码:

#include"iostream"

usingnamespacestd;

classLink{

public:

intm;

Link*next;

Link(inta=0,Link*b=NULL){

m=a;

next=b;

}

};

classLList{

private:

Link*head;

Link*tail;

Link*curr;

intcnt;

voidinit(){//初始化链表

curr=tail=head=newLink;

tail->next=head;

cnt=0;

}

voidremoveall(){//清空链表

tail->next=NULL;

while(head!

=NULL){

curr=head;

head=head->next;

deletecurr;

}

}

public:

LList(){init();}

~LList(){removeall();}

voidsethead(inta){//输入头结点

head->m=a;

cnt++;

}

voidprint(){//打印链表中的元素

Link*i1=curr;

Link*i2=curr;

while(i1->next!

=i2){

cout<m<<"";

i1=i1->next;

}

cout<m<<"";

//curr=head;

}

voidlclear(){//清空链表

removeall();

init();

}

voidinset(inta){//插入元素

curr->next=newLink(a,curr->next);

if(tail==curr)tail=curr->next;

cnt++;

}

voidappend(inta){//添加元素

tail=tail->next=newLink(a,NULL);

tail->next=head;

cnt++;

}

intremove(){//删除元素

if(curr->next==NULL){

cout<<"noelement"<

return0;

}

inta=curr->next->m;

Link*it=curr->next;

if(curr->next==tail){

tail=curr;

}

curr->next=curr->next->next;

deleteit;

cnt--;

returna;

}

voidprev(){//移动到前一个元素

Link*temp=curr;

while(temp->next!

=curr)

temp=temp->next;

curr=temp;

}

voidnext(){//移动到下一元素

curr=curr->next;

}

intlength()//链表长度

{

returncnt;

}

intcurrpos(){//当前元素的位置

Link*temp=head;

inti=0;

while(temp!

=curr){

temp=temp->next;

i++;

}

returni;

}

voidmovetopos(intpos){//移动到该位置

//Assert((pos>=0)&&)(pos<=cnt),"positionoutofrange");

curr=head;

for(inti=0;i

curr=curr->next;

}

}

intgetvalue(){//获取下一个元素的值

//Assert(curr->next!

=NULL,"novalue");

returncurr->next->m;

}

intgetcurr(){

returncurr->m;

}

};

intshaixuan(LList&a,intb){

intc,i;

//cout<

for(i=1;;i++){

if(i==b){

c=a.getcurr();

a.prev();

//cout<<"dq"<

cout<

a.next();

//cout<<"qqq"<

break;

}

//cout<<"changd"<

a.next();

}

returnc;

}

intmain(){

LLista;

intb,c;

cout<<"输入首结点"<

cin>>b;

a.sethead(b);

cout<<"添加元素结束输入0结束"<

inti=1;

for(;;){

cin>>i;

if(i==0){

break;

}

a.append(i);

}

cout<<"输入上限"<

cin>>c;

for(;a.length()!

=0;){

c=shaixuan(a,c);

}

return0;

}

结果:

实验四农夫过河问题的求解

1.问题描述

一个农夫带着一只狼、一只羊和一棵白菜,身处河的南岸。

他要把这些东西

全部运到北岸。

他面前只有一条小船,船只能容下他和一件物品,另外只有农夫

才能撑船。

如果农夫在场,则狼不能吃羊,羊不能吃白菜,否则狼会吃羊,羊会

吃白菜,所以农夫不能留下羊和白菜自己离开,也不能留下狼和羊自己离开,而

狼不吃白菜。

请求出农夫将所有的东西运过河的方案。

2.实现提示

求解这个

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 考试认证 > 交规考试

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1