当前位置:文档之家› 数据结构与算法分析专题实验-西安交大-赵仲孟

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

西安交通大学数据结构与算法课程实验实验名称:数据结构与算法课程专题实验所属学院:电信学院专业班级:计算机32班小组成员:指导老师:赵仲孟教授实验一背包问题的求解1.问题描述假设有一个能装入总体积为T的背包和n件体积分别为w1,w2,…w n的物品,能否从n件物品中挑选若干件恰好装满背包,即使w1+w2+…+w m=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"using namespace std;class Link{public:int m;Link *next;Link(int a=0,Link *b=NULL){m=a;next=b;}};class LStack{private:Link *top;int size;int a[100];public:LStack(int sz=0){top=NULL;size=0;a[0]=0;}~LStack(){clear();}void clear(){while(top!=NULL){Link *temp=top;top=top->next;delete temp;}size=0;}void push(int it, int b){top=new Link(it,top);a[size]=b;size++;}int pop(){int it=top->m;Link * ltemp=top->next;delete top;top=ltemp;size--;return it;}int topValue(){return top->m;}int length(){return size;}int sum(){int s=0;for(int i=0;i<size;i++)s=s+a[i];return s;}void print(){for(int i=0;i<size;i++)cout<<a[i]<<" ";cout<<endl;}};void panduan(int x1,int n, int x2[],LStack *x4){ int i,ss=0;for(i=x4->pop()+1;i<n;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 ;else panduan(x1, n,x2,x4);}int main(){LStack *ll=new LStack(0);int m[100];int n,z;cout<<"输入物品个数"<<endl;cin>>n;cout<<"输入物品大小"<<endl;for(int i=0;i<n;i++)cin>>m[i];cout<<"输入背包大小"<<endl;cin>>z;ll->push(-1,0);cout<<"符合条件的解"<<endl;panduan(z,n,m,ll);return 0;}结果1:代码2:#include<iostream># include<cstring>using namespace std;struct Bag{int V; //背包体积int number; //物品数量int v[20]; //物品体积int value[20]; //物品价值int dp[20][20]; //最大价值}bag;int max(int a,int b){return a>b?a:b;}int main(){cout<<"请输入背包的容量:"<<endl;cin>>bag.V;cout<<"请输入物品的数量:"<<endl;cin>>bag.number;cout<<"请输入每件物品的体积:"<<endl;for(int i=1;i<=bag.number;i++){cin>>bag.v[i];}cout<<"请输入每件物品的价值:"<<endl;for(int i=1;i<=bag.number;i++){cin>>bag.value[i];}memset(bag.dp,0,sizeof(bag.dp)); //dp中的每一个元素置零for(int i=1;i<=bag.number;i++)for(int j=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]);elsebag.dp[i][j]=bag.dp[i-1][j];}cout<<"最大价值:"<<bag.dp[bag.number][bag.V]<<endl;return 0;}结果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"using namespace std;class BSTNode{public:double it;BSTNode *lc;BSTNode *rc;BSTNode(){lc=rc=NULL;}BSTNode(double a,BSTNode* l=NULL, BSTNode* r=NULL){it=a;lc=l;rc=r;}~BSTNode(){}double getele(){return it;}void setele(double a){it=a;}inline BSTNode* getlc(){return lc;}inline BSTNode* getrc(){return rc;}inline void setlc(BSTNode* a){lc=a;}inline void setrc(BSTNode * a){rc=a;}bool isleaf(){return (lc==NULL&&rc==NULL);}};class BST{friend class BSTNode;private:BSTNode *root;int nodecount;int cd;void clearhelp(BSTNode*);bool findhelp(BSTNode*, double );BSTNode* getmin(BSTNode*);BSTNode*deletemin(BSTNode*);BSTNode* insethelp(BSTNode*, double);BSTNode* removehelp(BSTNode*, double);void printhelp(BSTNode* ,int );public:BST(){root=NULL;nodecount=0;cd=0;}~BST(){clearhelp(root);}void clear(){clearhelp(root);nodecount=0;}void inset(double a){root=insethelp(root, a);}double remove(double a){if(findhelp(root,a)){root=removehelp(root,a);nodecount--;cd--;}elsecout<<"无"<<a<<endl;}void print(){if(root==NULL)cout<<"Tree is empty"<<endl;elseprinthelp(root,0);}void chazhaochangdu(){int a;a=cd/nodecount;cout<<a<<endl;}};bool BST::findhelp(BSTNode* root, double a){if(root==NULL)return false;if(a<root->it)return findhelp(root->lc,a);else if(a>root->it)return findhelp(root->rc,a);else if(a==root->it)return true;}BSTNode* BST::insethelp(BSTNode* root, double a){ if(root==NULL){ cd++;nodecount++;return new BSTNode(a,NULL,NULL);}if(a<=root->it){ cd++;root->setlc(insethelp(root->lc,a));}else if(a>root->it){ cd++;root->setrc(insethelp(root->rc,a));}return root;}BSTNode* BST:: deletemin(BSTNode* rt){if(rt->lc==NULL)return rt->rc;else {rt->setlc(deletemin(rt->lc));return rt;}}BSTNode* BST:: getmin(BSTNode* rt){if(rt->lc==NULL)return rt;else return getmin(rt->lc);}BSTNode* BST::removehelp(BSTNode* rt,double a){ if(rt==NULL) return NULL;else if(a<rt->it)rt->setlc(removehelp(rt->lc,a));else if(a>rt->it)rt->setrc(removehelp(rt->rc,a));else{BSTNode* temp=rt;if(rt->lc==NULL){rt=rt->rc;delete temp;}else if(rt->rc==NULL){rt=rt->lc;delete temp;}else {BSTNode* temp=getmin(rt->rc);rt->it=temp->it;rt->setrc(deletemin(rt->rc));delete temp;}}return rt;}void BST:: clearhelp(BSTNode* root){if(root==NULL) return;clearhelp(root->lc);clearhelp(root->rc);delete root;}void BST:: printhelp(BSTNode* root ,int level){ if(root==NULL)return ;printhelp(root->lc,level+1);cout<<root->it<<" ";printhelp(root->rc,level+1);}int main(){BST a;string b;int i;cout<<"输入数据以\\n结束"<<endl;for(;;){cin>>b;if(b.at(0)=='\\'){break;}else{a.inset(atof(b.c_str()));}}a.print();cout<<endl<<"二叉树的平均搜索长度";a.chazhaochangdu();for(; ;){cout<<"输入要删除的数"<<endl;double x;cin>>x;a.remove(x);a.print();}return 0;}结果:实验三约瑟夫环1.问题描述设编号为1,2,…,n(n>0)个人按顺时针方向围坐一圈,每人持有一个正整数密码。

相关主题