数据结构实践报告文库版.docx

上传人:b****6 文档编号:7167283 上传时间:2023-01-21 格式:DOCX 页数:64 大小:507.78KB
下载 相关 举报
数据结构实践报告文库版.docx_第1页
第1页 / 共64页
数据结构实践报告文库版.docx_第2页
第2页 / 共64页
数据结构实践报告文库版.docx_第3页
第3页 / 共64页
数据结构实践报告文库版.docx_第4页
第4页 / 共64页
数据结构实践报告文库版.docx_第5页
第5页 / 共64页
点击查看更多>>
下载资源
资源描述

数据结构实践报告文库版.docx

《数据结构实践报告文库版.docx》由会员分享,可在线阅读,更多相关《数据结构实践报告文库版.docx(64页珍藏版)》请在冰豆网上搜索。

数据结构实践报告文库版.docx

数据结构实践报告文库版

学校

数据结构课程实践

实验报告1、2、3、4

姓名:

日期:

1.约瑟夫环问题

(1)问题描述

约瑟夫(Joseph)问题的一种描述是:

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

开始时任选一个整数作为报数上限值m,从一个人开始顺时针自1开始顺序报数,报到m时停止报数。

报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有的人全部出列为止。

要求设计一个程序模拟此过程,求出出列顺序。

(2)设计要求

设计一个程序,以人机交互方式执行,用户指定约瑟夫环游戏的总人数n和初始的报数上限m,然后输入每个人所持有的密码key。

模拟约瑟夫环,从头开始报数,直到所有的人出列。

系统按照出列顺序给出编号。

(3)数据结构

本设计利用带头结点的单循环链表作为模拟约瑟夫环游戏的存储结构。

(4)分析与实现

首先我们应该分析一下问题,一共有n个人,编号1,2,3..n每个人有一个key,那么我们采用一个节点代表一个人,每个人有两个属性:

1.编号2.Key我们可以使用一个如下的结构代表人,同时用循环链表表示围成一圈的状态。

/*数据域结构体*/

typedefstruct{

intno;//属性1

intkey;//属性2

}LElemType_L;

/*单链表结构体*/

typedefstructLNode

{

LElemType_Ldata;

structLNode*next;

}LNode;

typedefLNode*LinkList;

接下来应该初始化数据空间

/*初始化单循环链表*/

StatusInitList_L(LinkList*L)

{

/*这里使用了一个特殊方法来标记头节点,就是头节点的数据是(-1)*/

*L=(LinkList)malloc(sizeof(LNode));

(*L)->data.no=-1;

(*L)->data.key=-1;

if(!

(*L))

exit(ERROR);

(*L)->next=*L;

returnOK;

}

使用一个函数来将数据存入数据表

/*获取数据:

参数是循环链表和获取的值的数量*/

voidgetData(LinkListmans,inti){

//向表的最后插入数据

for(intj=0;j

LinkListtemp;

temp=mans->next;

while(temp->next!

=mans)

{

temp=temp->next;

}

LElemType_Le;

e.no=j+1;

printf("请输入第%d个KEY\n",j+1);

scanf("%d",&e.key);

LinkListnew=malloc(sizeof(LNode));

new->data=e;

new->next=temp->next;

temp->next=new;

}

}

核心函数,模拟报数的过程,并且正确的处理头节点和数据节点的关系。

/*约瑟夫(KEY)*/

/*参数列表,开始移动的节点(其next节点是下一个),将要被删除的节点位置m,还剩的节点数flag*/

voidJoseph(LinkListlast,intm,intflag){

//链表删除完之后就会使flag为0

if(flag==0){

return;

}else{

//temp指向即将被删除的元素的前驱

LinkListtemp=last;

/*首先使头节点前进m-1*/

for(inti=1;i

/*头节点的特殊处理,越过头节点*/

if(temp->next->data.no==-1){

temp=temp->next;

}

++i;

temp=temp->next;

}

/*头节点的特殊处理,越过头节点*/

if(temp->next->data.no==-1){

temp=temp->next;

}

/*输出元素并且删除节点*/

LElemType_Le;

LinkListdele=temp->next;

e=dele->data;

temp->next=dele->next;

free(dele);

printf("%d\t",e.no);

/*递归进行下一次操作*/

Joseph(temp,e.key,--flag);

}

}

主函数:

进行测试

intmain(intargc,char*argv[]){

LinkListmans;

InitList_L(&mans);

/*进行参数化获取数据*/

intn=0;

printf("请输入总人数n\n");

scanf("%d",&n);

/*获取指定数量的数据*/

getData(mans,n);

intm=2;

printf("请输入第一个数m\n");

scanf("%d",&m);

/*运行算法求解*/

Joseph(mans,m,n);

return0;

}

(5)运行与测试

首先确定一个有五个人的测试集,每个人的key分别是1,3,5,7,9m取值

为3首先手动模拟过程,得到测试集的结果是3,4,5,1,2.。

然后使用程序重复相同的步骤:

从运行结果来看程序的结果准确。

(6)总结与思考

通过解决约瑟夫环的问题,我熟悉了单循环链表的结构和使用方式。

通过该过程,我对循环结构的链表有了全新的认识,对于约瑟夫环这种问题使用单循环链表来解决可谓是轻而易举。

我对数据结构的作用有了全新的思考,我意识到掌握数据结构的本领对今后的发展大有帮助。

(7)完整代码

#include

#include

#include

/*定义几个状态码*/

#defineOK1

#defineERROR0

#defineTRUE1

#defineFALSE0

/*状态码的数据类型int*/

typedefintStatus;

/*数据域结构体*/

typedefstruct{

intno;

intkey;

}LElemType_L;

/*单链表结构体*/

typedefstructLNode

{

    LElemType_Ldata;

    structLNode*next;

}LNode;

typedefLNode*LinkList;

/*初始化单循环链表*/

//StatusInitList_L(LinkList*L)

//{

//*L=(LinkList)malloc(sizeof(LNode));

///*这里使用了一个特殊方法来标记头节点,就是头节点的数据是(-1)*/

//(*L)->data.no=-1;

//(*L)->data.key=-1;

//(*L)->next=*L;

//  returnOK;

//}

StatusInitList_L(LinkList*L)

{

*L=(LinkList)malloc(sizeof(LNode));

/*这里使用了一个特殊方法来标记头节点,就是头节点的数据是(-1)*/

(*L)->data.no=-1;

(*L)->data.key=-1;

(*L)->next=*L;

returnOK;

}

/*获取数据:

参数是循环链表和获取的值的数量*/

voidgetData(LinkListmans,inti){

//向表的最后插入数据

for(intj=0;j

LinkListtemp;

temp=mans->next;

while(temp->next!

=mans)

{

temp=temp->next;

}

LElemType_Le;

e.no=j+1;

printf("请输入第%d个KEY\n",j+1);

scanf("%d",&e.key);

LinkListnew=malloc(sizeof(LNode));

new->data=e;

new->next=temp->next;

temp->next=new;

}

}

/*约瑟夫(KEY)*/

/*参数列表,开始移动的节点(其next节点是下一个),将要被删除的节点位置m,还剩的节点数flag*/

voidJoseph(LinkListlast,intm,intflag){

//链表删除完之后就会使flag为0

if(flag==0){

return;

}else{

//temp指向即将被删除的元素的前驱

LinkListtemp=last;

/*首先使头节点前进m-1*/

for(inti=1;i

/*头节点的特殊处理,越过头节点*/

if(temp->next->data.no==-1){

temp=temp->next;

}

++i;

temp=temp->next;

}

/*头节点的特殊处理,越过头节点*/

if(temp->next->data.no==-1){

temp=temp->next;

}

/*输出元素并且删除节点*/

LElemType_Le;

LinkListdele=temp->next;

e=dele->data;

temp->next=dele->next;

free(dele);

printf("%d\t",e.no);

/*递归进行下一次操作*/

Joseph(temp,e.key,--flag);

}

}

intmain(intargc,char*argv[]){

    LinkListmans;

    InitList_L(&mans);

    /*进行参数化获取数据*/

    intn=0;

    printf("请输入总人数n\n");

    scanf("%d",&n);

    /*获取指定数量的数据*/

    getData(mans,n);

    intm=2;

    printf("请输入第一个数m\n");

    scanf("%d",&m);

    /*运行算法求解*/

    Joseph(mans,m,n);

return0;

}

2.停车场管理

(1)问题描述

设停车场内只有一个可停放n辆汽车的狭长通道,且只有一个大门可供汽车进出。

汽车在停车场内按车辆到达时间的先后顺序,依次由北向南排列(大门在最南端,最先到达的第一辆车停放在车场的最北端),若停车场已停满n辆汽车,则后来的汽车只能在门外的便道上等候,一旦有车开走,则排在便道上的第一辆车即可开入;当停车场内某辆车要离开时,在其之后开入的车辆必须先退出停车场让路,待该辆车开出大门外,其他车辆再按原次序进入停车场,每辆停放在停车场的车在其离开停车场时必须按其停留的时间长短交纳费用。

试为停车场编制按上述要求进行管理的模拟程序。

(2)设计要求

以栈模拟停车场,以队列模拟停车场外的便道,按照从终端读入的输入数据的方式进行模拟管理。

输入1,表示车辆到达;输入2,表示车辆离开;输入3,表示显示出停车场内及便道上的停车情况;输入4,表示退出系统。

车辆到达操作,需输入汽车牌照号码及到达时间;车辆离开操作,需输入汽车在停车场的位置及离开时刻,且应输出汽车在停车场内停留的时间和应缴纳的费用(在便道上停留的时间不收费)。

(3)数据结构

本设计使用数据结构是顺序栈和链式队列。

(4)分析与实现

使用顺序栈和队列实现该程序,顺序栈来表示停车场,队列表示便道,当有车需要入库的时候首先判断车库是不是满了,满了之后就应该到队列中等候,如果没有满,那么就应该入库并且开始将入库时间记录好。

当有车出库的时候将该车入库的时间取出来,计算在库中停留的时间并输出应缴纳的停车费,此时车已经出栈,应该判断队列中是否有车等候,如果有车等候那么就将队头那辆车入库并且保存入库时间表示收费开始。

数据结构:

//每辆车存放信息

typedefstruct{

intno;//车牌号

Datetime;//时间

}DataType;

typedefstruct/*顺序栈定义*/

{

DataTypedata[MAXNUM];/*存放栈的数据元素*/

inttop;/*栈顶指针,用来存放栈顶元素在数组中的下标*/

}SeqStack;

typedefstructLQNode/*链队结点结构*/

{

DataTypeinfo;

structLQNode*next;

}LQNode;

typedefstruct/*链接队列类型定义*/

{

structLQNode*front;/*头指针*/

structLQNode*rear;/*尾指针*/

}LinkQueue;

创建新队列

LinkQueue*LQueueCreateEmpty()/*创建空链队,返回头指针*/

{

LinkQueue*plq=(LinkQueue*)malloc(sizeof(LinkQueue));

if(plq!

=NULL)

plq->front=plq->rear=NULL;

else

{

printf("内存不足!

!

\n");

returnNULL;

}

returnplq;

}

判断队列是否为空

intLQueueIsEmpty(LinkQueue*plq)/*判断链接表示队列是否为空队列*/

{

return(plq->front==NULL);

}

队列的入队

voidLQueueEnQueue(LinkQueue*plq,DataTypex)/*入链队*/

{

LQNode*p=(LQNode*)malloc(sizeof(LQNode));

if(p==NULL)

printf("内存分配失败!

\n");

else

{

p->info=x;

p->next=NULL;

if(plq->front==NULL)/*原来为空队*/

plq->front=p;

else

plq->rear->next=p;

plq->rear=p;

}

}

队列的出队

intLQueueDeQueue(LinkQueue*plq,DataType*x)/*出链队*/

{

LQNode*p;

if(plq->front==NULL)

{

printf("队列空!

!

\n");

returnERROR;

}

else

{

p=plq->front;

*x=p->info;

plq->front=plq->front->next;

free(p);

returnOK;

}

}

求队列长度

intLQueueSize(LinkQueue*LQ){

intn=0;

DataTypee;

LinkQueue*temp;

temp=LQueueCreateEmpty();

while(!

LQueueIsEmpty(LQ)){

n++;

LQueueDeQueue(LQ,&e);

LQueueEnQueue(temp,e);

}

while(!

LQueueIsEmpty(temp)){

LQueueDeQueue(temp,&e);

LQueueEnQueue(LQ,e);

}

returnn;

}

将栈置为空栈

voidSStackSetNull(SeqStack*s)/*置空栈*/

{

s->top=-1;

}

判断栈是不是为空

intSStackIsEmpty(SeqStack*s)/*判断栈S为空栈时返回值为真,反之为假*/

{

return(s->top<0?

TRUE:

FALSE);

}

判断栈是不是满了

intSStackIsFull(SeqStack*s)/*判断栈S为满栈时返回值为真,反之为假*/

{

return(s->top==MAXNUM-1?

TRUE:

FALSE);

}

入栈

intSStackPush(SeqStack*s,DataTypex)

{

if(s->top==MAXNUM-1)

{

printf("栈上溢出!

\n");

returnFALSE;

}

else

{

s->top=s->top+1;

s->data[s->top]=x;

returnTRUE;

}

}

出栈

intSStackPop(SeqStack*s,DataType*x)

{

if(s->top==-1)

{

printf("栈下溢出!

\n");

returnFALSE;

}

else

{

*x=s->data[s->top];

s->top--;

returnTRUE;

}

}

显示栈中的元素数量

/*返回当前堆栈中元素的数量*/

intSqStackSize(SeqStack*CheKu){

intn=0;

DataTypeoldcar;

SeqStackTemp;

SStackSetNull(&Temp);

//计数

while(!

SStackIsEmpty(CheKu)){

n++;

SStackPop(CheKu,&oldcar);

SStackPush(&Temp,oldcar);

}

while(!

SStackIsEmpty(&Temp)){

SStackPop(&Temp,&oldcar);

SStackPush(CheKu,oldcar);

}

returnn;

}

打印停车场中的所有车

voidSStackPrint(SeqStack*s)

{

intp;

if(SStackIsEmpty(s)==TRUE)

printf("车库是空的!

\n");

else

{

printf("-------\n");

p=0;

while(p<=s->top)

{

printf("|﹀%d%d/%d\n",s->data[p].no,s->data[p].time.day,s->data[p].time.hour);

p++;

}

printf("\n");

}

}

停车函数

/*停车函数*/

voidpark(SeqStack*CheKu,LinkQueue*DuiLie,DataTypecar)

{

//首先判断车库是不是空的

if(SStackIsFull(CheKu)){

//车库已经满了,那么应该进入队列等候

LQueueEnQueue(DuiLie,car);

printf("当前车库已经满了,车辆进入便道等候\n");

}else{

//车库没有满就直接让车进入车库

SStackPush(CheKu,car);

printf("车辆已经进入车库同时按照输入的时间开始计费\n");

}

}

取车函数

/*取车函数*/

voidunPark(SeqStack*CheKu,LinkQueue*DuiLie,DataTypecar){

SeqStackTemp;

SStackSetNull(&Temp);

DataTypeoldcar;

Datetime=car.time;

while(!

SStackIsEmpty(CheKu)){

SStackPop(CheKu,&oldcar);

//查找目标车辆

if(oldcar.no!

=car.no){

//非目标车辆压入临时库

SStackPush(&Temp,oldcar);

}else{

//找到目标车后输出

intday=time.day-oldcar.time.day;

inthour=time.hour-oldcar.time.hour;

if(hour<0){

day--;

hour=24+hour;

}

printf("车%d出库停留时间%dd%dh应缴纳费用¥%d\n",oldcar.no,day,hour,(24*day+hour)*PRICE);

}

}

//将所有车辆放回库中

while(!

SStackIsEmpty(&Temp)){

SStackPop(&Temp,&oldcar);

SStackPush(CheKu,oldcar);

}

//此时车库应该是有空位的如果队列中有车那么应该将一辆车从便道移动到车库

if(!

LQueueIsEmpty(DuiLie)){

LQueueDeQueue(DuiLie,&oldcar);

oldcar.time=time;

SStackPush(CheKu,oldcar);

printf("队列中的%d已经移动到库中开始计时的时间是%d/%d\n",oldcar.no,oldcar.time.day,oldcar.time.hour);

}

}

显示当前停车场的状态

/*显示系统状态*/

voidshowsta(SeqStack*CheKu,LinkQueue*DuiLie){

intn=0;

n=SqStackSize(CheKu);

if(!

SStackIsFull(CheKu)){

printf("\n车库是有空位的\t空位有:

%d个\n",MAXNUM-n);

}else{

printf("\n车库已经满了!

便道有%d辆车等候\n",LQueueSize(DuiLie));

}

}

显示当前便道的等待状态

voidshowLQ(LinkQueue*LQ){

DataTypee;

LinkQueue*temp;

temp=LQueueCreateEmpty();

printf("队列:

\n");

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

当前位置:首页 > 表格模板 > 合同协议

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

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