数据结构课程设计修道士野人问题和西文图书管理系统.docx

上传人:b****4 文档编号:12340843 上传时间:2023-04-18 格式:DOCX 页数:42 大小:245.05KB
下载 相关 举报
数据结构课程设计修道士野人问题和西文图书管理系统.docx_第1页
第1页 / 共42页
数据结构课程设计修道士野人问题和西文图书管理系统.docx_第2页
第2页 / 共42页
数据结构课程设计修道士野人问题和西文图书管理系统.docx_第3页
第3页 / 共42页
数据结构课程设计修道士野人问题和西文图书管理系统.docx_第4页
第4页 / 共42页
数据结构课程设计修道士野人问题和西文图书管理系统.docx_第5页
第5页 / 共42页
点击查看更多>>
下载资源
资源描述

数据结构课程设计修道士野人问题和西文图书管理系统.docx

《数据结构课程设计修道士野人问题和西文图书管理系统.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计修道士野人问题和西文图书管理系统.docx(42页珍藏版)》请在冰豆网上搜索。

数据结构课程设计修道士野人问题和西文图书管理系统.docx

数据结构课程设计修道士野人问题和西文图书管理系统

题号题目3、修道士与野人问题

1、需求分析

n个修道士和n个野人渡河,只有一条小船,能容纳c人,两种人都会划船,建立过河方式。

满足:

野人无法侵犯修道士。

这就要求无论在何处,修道士的个数不得少于野人的人数(除非修道士个数为0)。

设计程序模拟该过程。

程序的输入为修道士(野人)的个数以及每条船容纳人的个数。

输出为判断是否可以安全渡河。

如果能,则给出一个小船来回次数最少的最佳方案。

要求:

(1)用一个三元组(x1,x2,x3)表示渡河过程中各个状态。

其中,x1表示起始岸上修道士个数,x2表示起始岸上野人个数,x3表示小船位置(0——在目的岸,1——在起始岸)。

例如(5,3,0)表示起始岸上有5个修道士,3个野人,小船在目的岸一边。

(2)采用邻接表做为存储结构。

最短路径搜索采用广度搜索法。

(3)输出最优解

若问题有解(能渡过河去),则输出一个最佳方案。

用三元组表示渡河过程中的状态,并用箭头指出这些状态之间的迁移:

目的状态←…中间状态←…初始状态。

若问题无解,则给出“渡河失败”的信息。

(4)求出所有的解。

2、设计

2.1设计思想

(1)数据结构设计:

根据题目要求,用图形结构,用邻接表来存储结点,以及结点之间的关系,同时在广度优先遍历中利用到队列。

(2)算法设计:

先定义一个图利用邻接表储存结构,再举出在船上修道士和野人的所有情况,然后判断其修道士是否处于安全的状态,如果安全则将该点添加到图中,点添加完后在看两点之间是否连通如果连通则可将边添加到图中,这样就创建出了图,然后分别利用广度搜索和深度搜索来完成题目的要求。

2.2设计表示

(1)函数调用关系图

 

(2)函数接口规则说明

intSearch(AdjLGraph*G,intx,inty,intm)/*查找起始和最后的结点,其中x,y,m分别表示起始岸修道士人数,野人人数和船的状态*/

intChecking(DataTypex)/*检查修道士是否安全,x表示邻接表中的一个结点*/

intConnect(AdjLGraph*G,inti,intj)/*将能走通的点连接起来,i,j为图中的两个结点*/

voidCreat(AdjLGraph*G)/*图的创建*/

intPrint(AdjLGraphG)/*从后向前打印最短路径*/

intBroadFSearch(AdjLGraphG,intu,intv)/*用广度优先遍历搜索最短路径,u表示起始结点,v表示最后的结点*/

voidPrint1(AdjLGraphG)/*打印输出所有最短路径*/

voidDFS(AdjLGraphG,intu,intv,intvisited[])/*利用深度搜索找出所有最短路径,u表示起始结点,v表示最后的结点,visited[]用来标记结点是否被访问*/

2.3详细设计

首先是定义邻接表

typedefstruct

{

intdaoshi;//道士

intyeren;//野人

intship;//船的位置

}DataType;

typedefstructNode//边结点的结构体

{

intdest;//邻接边的弧头顶点序号

structNode*next;//单链表的下一个结点指针

}Edge;

typedefstruct

{

DataTypedata;//顶点数据元素

intsource;//弧尾顶点序号

Edge*adj;//邻接边的头指针

}AdjLHeight;

typedefstruct

{

AdjLHeighta[200];//邻接表数组

intnumOfVerts;//顶点个数

intnumOfEdges;//边个数

}AdjLGraph;//邻接表结构体

同时定义了几个全局变量,便于函数的直接利用

intn,c;//修道士和野人人数为n,船能容纳人数为c

intPath[200];//保存结点的后驱结点

intPath1[200];//保存结点的前驱结点

利用上述结构和相关函数可以构造出图,然后对图进行利用;

然后在广度优先遍历搜索中用到了队列

typedefstruct

{

intqueue[200];

intrear;

intfront;

intcount;

}SeqCQueue;

最后通过主函数main调用各函数得到相关信息

intmain()

{

AdjLGraphG;

intvisited[200];//标记结点是否被访问

printf("输入小船可装的人数:

\n");

while(scanf("%d",&c)!

=EOF)

{

memset(Path,0,sizeof(0));

memset(visited,0,sizeof(visited));

memset(Path1,0,sizeof(Path1));

N=0;

printf("输入野人或修道士的个数:

\n");

scanf("%d",&n);

AdjInitiate(&G);

Creat(&G);

v1=Search(&G,n,n,1);

v2=Search(&G,0,0,0);

if(BroadFSearch(G,v1,v2)==0)

printf("渡河失败\n");

else{

printf("输出所有最短路径的情况:

\n");

DFS(G,v1,v2,visited);

printf("共有%d种情况\n",N);

}

printf("输入小船可装的人数:

\n");

}

return0;

}

3、调试分析

在进行运行的时候,曾出现了打印输出错误,经过一步一步调试,发现在插入结点的时候出现了插入错误,即没有考虑到结点后驱的改变,通过改正,重新运行检测,运行结果正确,在排版时通过一步步调试,能够使输出结果很明显的表示的船的方案。

4、用户手册

在VC下运行,很简单的输入,只需输入野人和道士的人数N和船能承载的人的个数C即可。

5、测试数据及测试结果

(1)输入修道士和野人的人数n=6,船能容纳的人c=2,;不能安全渡河;

测试结果:

(2)输入修道士和野人人数为n=3,船能容纳的人c=2;渡河成功

测试结果:

输出一种最短路径

输出所有最短路径

输出最短路径数目:

6、源程序清单

#include

#include

#include

#include

intn,c;//修道士和野人人数为n,船能容纳人数为c

intPath[200];//保存结点的后驱结点

intPath1[200];//保存结点的前驱结点

typedefstruct

{

intdaoshi;//道士

intyeren;//野人

intship;//船的位置

}DataType;

typedefstructNode//边结点的结构体

{

intdest;//邻接边的弧头顶点序号

structNode*next;//单链表的下一个结点指针

}Edge;

typedefstruct

{

DataTypedata;//顶点数据元素

intsource;//弧尾顶点序号

Edge*adj;//邻接边的头指针

}AdjLHeight;

typedefstruct

{

AdjLHeighta[200];//邻接表数组

intnumOfVerts;//顶点个数

intnumOfEdges;//边个数

}AdjLGraph;//邻接表结构体

voidAdjInitiate(AdjLGraph*G)//初始化

{

inti;

G->numOfEdges=0;//图的边数

G->numOfVerts=0;//顶点数

for(i=0;i<200;i++)

{

G->a[i].source=i;

G->a[i].adj=NULL;

}

}

voidInsertVertex(AdjLGraph*G,inti,DataTypex)//插入顶点

{

if(i>=0&&i<200)

{

G->a[i].data.daoshi=x.daoshi;//修道士人数

G->a[i].data.yeren=x.yeren;//野人人数

G->a[i].data.ship=x.ship;//船的状态

G->numOfVerts++;

}

elseprintf("顶点越界\n");

}

voidInsertEdge(AdjLGraph*G,inti,intj)//插入边

{

Edge*p;

if(i<0||i>=G->numOfVerts||j<0||j>=G->numOfVerts)

{

printf("参数i或j越界出错!

\n");

return;

}

p=(Edge*)malloc(sizeof(Edge));//申请邻接边单链表结点空间

p->dest=j;//置邻接边弧头序号

p->next=G->a[i].adj;//

G->a[i].adj=p;

G->numOfEdges++;

}

voidAdjDestroy(AdjLGraph*G)//释放指针内存空间

{

inti;

Edge*p,*q;

for(i=0;inumOfVerts;i++)//依次释放内存空间

{

p=G->a[i].adj;

while(p!

=NULL)

{

q=p->next;

free(p);

p=q;

}

}

}

//队列

typedefstruct

{

intqueue[200];

intrear;

intfront;

intcount;

}SeqCQueue;

//初始化

voidQueueInitiate(SeqCQueue*Q)

{

Q->rear=0;

Q->front=0;

Q->count=0;

}

//非空否

intQueueNotEmpty(SeqCQueueQ)

{

if(Q.count!

=0)return1;

elsereturn0;

}

//入队列

intQueueAppend(SeqCQueue*Q,intx)

{

if(Q->count>0&&Q->rear==Q->front)

{

printf("队列已满无法插入!

\n");

return0;

}

else

{

Q->queue[Q->rear]=x;

Q->rear=(Q->rear+1)%200;

Q->count++;

return1;

}

}

//出队列

intQueueDelete(SeqCQueue*Q,int*d)

{

if(Q->count==0)

{

printf("队列已空无数据元素出队列!

\n");

return0;

}

else

{

*d=Q->queue[Q->front];

Q->front=(Q->front+1)%200;

Q->count--;

return1;

}

}

//取队头数据元素

intQueueGet(SeqCQueueQ,int*d)

{

if(Q.count==0)

{

printf("队列已空无数据元素可取!

\n");

return0;

}

else

{

*d=Q.queue[Q.front];

return1;

}

}

//查找起始和最后的结点

intSearch(AdjLGraph*G,intx,inty,intm)

{

inti;

for(i=0;inumOfVerts;i++)

if(G->a[i].data.daoshi==x&&G->a[i].data.yeren==y

&&G->a[i].data.ship==m)

returni;

return-1;

}

intChecking(DataTypex)//检查修道士是否安全

{

if((x.daoshi>=x.yeren||x.daoshi==0)&&((n-x.daoshi)>=(n-x.yeren)||x.daoshi==n)&&

x.daoshi>=0&&x.daoshi<=n&&x.yeren>=0&&x.yeren<=n)

return1;

elsereturn0;

}

//将能走通的点连接起来

intConnect(AdjLGraph*G,inti,intj)

{

intm;

m=(G->a[i].data.daoshi-G->a[j].data.daoshi)+(G->a[i].data.yeren-G->a[j].data.yeren);

if(G->a[i].data.ship==0&&G->a[j].data.ship==0||G->a[i].data.ship==1&&G->a[j].data.ship==1)

return0;//两个结点都在此岸或都在对岸,不连通

elseif(G->a[i].data.ship==1&&G->a[j].data.ship==0)//从起始岸到目的岸人数要减少

{

if(G->a[j].data.daoshi>G->a[i].data.daoshi||G->a[j].data.yeren>G->a[i].data.yeren)

//----------如果J结点的道士或野人的个数比开始船没从I开到J时还大时

return0;

if(G->a[j].data.daoshi==G->a[i].data.daoshi&&G->a[j].data.yeren==G->a[i].data.yeren)

return0;

if(m>c)return0;//------------船上的人超重

return1;

}

elseif(G->a[i].data.ship==0&&G->a[j].data.ship==1)

{

//-----------------------从终点到起始最后人应该有所增加

if(G->a[j].data.daoshia[i].data.daoshi||G->a[j].data.yerena[i].data.yeren)

//----------如果J结点的道士或野人的个数比开始船没从I开到J时还小时

return0;

if(G->a[j].data.daoshi==G->a[i].data.daoshi&&G->a[j].data.yeren==G->a[i].data.yeren)

return0;

if((-1)*m>n)return0;//------------船上的人超重

return1;

}

return0;

}

//创建图

voidCreat(AdjLGraph*G)

{

inti,j,k,m;

m=0;

DataTypex;

for(k=0;k<=1;k++)//船有两种情况,在对岸和在起始岸

{

for(i=0;i<=n;i++)

for(j=0;j<=n;j++)

{

x.daoshi=i;

x.yeren=j;

x.ship=k;

if(Checking(x)==1)

{

InsertVertex(G,m,x);

m++;

}

}

}

for(i=0;inumOfVerts;i++)

for(j=0;jnumOfVerts;j++)

if(Connect(G,i,j))

{

InsertEdge(G,i,j);

}

}

intN;//渡河成功的总次数

intM;//最短路径

intv1;//起始点

intv2;//终点

//从后向前打印最短路径

intPrint(AdjLGraphG)

{

intk,i=0;

printf("(%d%d%d)<-----",G.a[v2].data.daoshi,G.a[v2].data.yeren,G.a[v2].data.ship);

for(k=Path1[v2];k!

=v1;k=Path1[k])

{

i++;

printf("(%d%d%d)<------",G.a[k].data.daoshi,G.a[k].data.yeren,G.a[k].data.ship);

}

printf("(%d%d%d)\n",G.a[v1].data.daoshi,G.a[v1].data.yeren,G.a[v1].data.ship);

returni;

}

//用广度优先遍历搜索最短路径

intBroadFSearch(AdjLGraphG,intu,intv)

{

Edge*p;

intvisit[200];//标记点是否被访问

intw,z;

memset(visit,0,sizeof(visit));//对数组visit[200]清零

SeqCQueueQ;

visit[u]=1;

QueueInitiate(&Q);

QueueAppend(&Q,u);

while(QueueNotEmpty(Q))

{

QueueDelete(&Q,&w);

p=G.a[w].adj;

while(p!

=NULL)

{

z=p->dest;

if(z==v)

{

Path1[z]=w;//---------------保存前驱

printf("输出一种最短路径的情况\n");

M=Print(G);

return1;

}

elseif(!

visit[z])//结点j未被访问过

{

Path1[z]=w;

visit[z]=1;

QueueAppend(&Q,z);

}

p=p->next;

}

}

return0;

}

voidPrint1(AdjLGraphG)

{

intk,j;

inti=0;

DataTypea1[200];

memset(a1,0,sizeof(a1));

for(k=Path[v1];k!

=v2;k=Path[k])

{

a1[0]=G.a[v1].data;

a1[i+1]=G.a[k].data;

i++;

}

if(i==M)

{

a1[i+1]=G.a[v2].data;

N++;

printf("(%d%d%d)",G.a[v1].data.daoshi,G.a[v1].data.yeren,G.a[v1].data.ship);

for(j=1;j<=M+1;j++)

{

printf("-->(%d%d)-->(%d%d%d)",abs(a1[j].daoshi-a1[j-1].daoshi),abs(a1[j].yeren-a1[j-1].yeren),a1[j].daoshi,a1[j].yeren,a1[j].ship);

}

printf("\n");

}

}

//利用深度搜索找出所有最短路径

voidDFS(AdjLGraphG,intu,intv,intvisited[])

{

Edge*p;

intw;

visited[u]=1;

p=G.a[u].adj;

while(p!

=NULL)

{

w=p->dest;

if(w==v)

{

Path[u]=w;//-----记下当前结点的后驱

Print1(G);

}

elseif(visited[w]==0){

Path[u]=w;

//找后驱,保存下来

DFS(G,w,v,visited);

}

p=p->next;

}

visited[u]=0;

}

intmain()

{

AdjLGraphG;

intvisited[200];//标记结点是否被访问

printf("输入小船可装的人数:

\n");

while(scanf("%d",&c)!

=EOF)

{

memset(Path,0,sizeof(0));

memset(visited,0,sizeof(visited));

memset(Path1,0,sizeof(Path1));

N=0;

printf("输入野人或修道士的个数:

\n");

scanf("%d",&n);

AdjInitiate(&G);

Creat(&G);

v1=Search(&G,n,n,1);

v2=Search(&G,0,0,0);

if(BroadFSearch(G,v1,v2)==0)

printf("渡河失败\n");

else{

printf("输出所有最短路径的情况:

\n");

DFS(G,v1,v2,visited);

printf("共有%d种情况\n",N);

}

printf("输入小船可装的人数:

\n");

}

return0;

}

 

题号题目6、西文图书管理系统

1、需求分析

图书管理基本业务活动包括:

对一本书的采编入库、清除库存、借阅和归还等等。

试设计一个图书管理系统,将上述业务活动借助于计算机系统完成。

要求:

(1)每种书的登记内容至少包括书号、书名、著者、现存量和总库存量等五项。

(2)作为演示系统,不必使用文件,全部数据可以都在内存存放。

要用B-树(4阶树)对书号建立索引,以获得高效率。

(3)系统应有以下功能:

采编入库、清除库存、借阅、归还、显示(以凹入表的形式显示)等。

2、设计

2.1设计思想

(1)数据结构设计:

本题要求用B_树来进行存储,其逻辑结构为树形结构,B_树有利于关键字的查找,是一种平衡多叉排序树。

(2)算法设计:

将比关键字小的元素插到该关键字的左孩子结点中,比关键字大的的元素插到该关键字的右孩子结点中,当一个结点中关键字的个数超过规定的个数时,该节点要进行分裂,并且保证所有的叶子结点都在同一层。

2.2设计表

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

当前位置:首页 > 医药卫生 > 临床医学

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

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