[实用参考]顺序表实现约瑟夫环的问题-C语言.doc

合集下载

C语言单向循环链表实现实现约瑟夫环

C语言单向循环链表实现实现约瑟夫环

C语言实现约瑟夫环问题------单向循环链表实现问题描述:有n个人围成一圈进行报数游戏,从第一个人开始报到m的人出圈,接下来有从下一个人开始,。

一次这样往复,直到最后一个人也出圈,求他们的出圈顺序?(例如8个人,凡报3的人出圈,则他们出圈顺序是3 ,6, 1,,5 ,2 ,8,4 ,7)#include<stdio.h>#include<stdlib.h>typedef struct node{int value;struct node *next;}NODE;//*********************建立循环链表(尾插法建立)***********//NODE *createlink(int number){NODE *head=NULL,*p=NULL,*q=NULL;int i=1;head=(struct node*)malloc(sizeof(struct node)); //***建立第一个节点***//head->value=i;p=head;for(i=2;i<=number;i++) //***建立剩下的number-1节点****//{q=(struct node*)malloc(sizeof(struct node));if(q==0) return 0;p->next=q;p=q;p->value=i;}p->next=head;return head;}//*****************建立约瑟夫环********************// void jose(NODE *p,int number,int n){int i,j,g=0;NODE *q=NULL;for(i=1;i<=number;i++){for(j=1;j<n-1;j++){p=p->next;}q=p->next; //***q用来记录要删除的节点*****//p->next=q->next; //****删去q节点******//p=p->next;printf("第%3d个出圈号是:%3d\n",i,q->value);free(q);}printf("\n");// p->next=NULL; 此表达式不能出现在此处,最后一个节点删除后就不存在了}//***********************主函数*************************//int main( ){int number=0;int n=0;printf("请输入总人数number和出拳编号n:\n");scanf("%d",&number);scanf("%d",&n);NODE *head=NULL;head=createlink(number);jose(head,number,n);system("PAUSE");return 1;}。

C实验报告约瑟夫斯环问题

C实验报告约瑟夫斯环问题

约瑟夫斯(Josephus)问题的一种描述是:编号为1,2,…,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。

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

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

试设计一个程序,按出列顺序印出各人编号。

2.基本要求:利用单向循环链表存储结构模拟此过程,按照出列的顺序印出各人的编号。

3.测试数据:m的初值为20;n=7,7个人的密码依次为:3,1,7,2,4,8,4。

m初值为6(正确的出列顺序应为6,1,4,7,2,3,5)。

4.简述每一部分的对象、目的和要求:(1)主函数部分:对象:链表;目的:创建新链表;要求:将该链表初始化。

(2)被调函数部分:对象:结构体;目的:创建循环链表并且模拟约瑟夫斯问题;要求:让链表首尾相接,并且释放原来单链表的头结点空间。

通过该函数的调用,依次输出各结点的编号,并且符合规则。

二.需求分析1.程序所能达到的基本可能:该程序用循环链表来模拟n个人顺时针围坐一圈,用链表中的每一个结点代表一个人,结点结构体中设置两个变量,分别存放其编号以及密码。

在输入初始密码后,对该链表进行遍历,直到遍历到第m个结点,释放其空间,使其出列。

然后用被释放空间结点的密码值作为新的密码值,重复上述过程,直至所有结点被释放空间出列,链表成为空链表。

2.输入输出形式及输入值范围:程序运行后显示提示信息:"Please input a data:",提示用户输入密码信息,在输入达预定次数后自动跳出该循环,同时循环链表创建成功,在主函数中有相应的输出给予检验。

然后程序显示提示信息:"Please input the number m:",提示用户输入初始密码,程序执行结束后会输出相应的出列结点的顺序,亦即其编号。

约瑟夫问题—顺序表完美实现

约瑟夫问题—顺序表完美实现
printf("输出约瑟夫序列\n");
for(i=pst->length;i>0;i--)
{
s1=(s1+m-1)%i;
w=pst->pbase[s1];
printf("%d ",w);
delete_Seqlist(pst,s1+1);
}
printf("\n");
return(1);
}
void init_list(PSeqlist pst,int length)
void delete_Seqlist(PSeqlist pst,int m);
int jose(PSeqlist pst,int s, int m);
int main(void)
{
int s,m;
Seqlist p1;
init_list(&p1,20);
input_list(&p1);
printf("请输入开始位置s和间隔数m : ");
1.代码
#include <stdio.h>
#include <malloc.h>
typedef struct list
{
int * pbase;
int maxsize;
int length;
}Seqlist,* PSeqlist;
void init_list(PSeqlist,int);
void input_list(PSeqlist);
{
scanf("%d",&x);
if (x == -1)
break;

约瑟夫环C 代码及实验报告

约瑟夫环C  代码及实验报告

{
outArray[k]=listArray[j];// 将 该 元 素 放 置 到 出 列 数 组
里,并输出
cout<<outArray[k]<<" ";
k++;
listArray[j]=0; //将出列元素置 0
i=1; //下一个元素从 1 开始重新报数
}
else
i++; //报数编号与出列编号不同时,继续报数
if(a[i]==1) {
j=j+a[i]; if(j==m) {
j=0; a[i]=0; k++; cout<<i<<" "; }
} if(i==n)
i=0; }
}
七、实验心得 李孟琪:该实验利用数组实现线性表,算法简便,但产生很多不必要的消耗,下 一步可以尝试采用单链表,双链表实现该问题。 李春阳:通过利用链表编写约瑟夫环,进一步掌握了约瑟夫环的原理,加深了对 链表使用的理解 雷鹤:这次实验遇到的最大问题是拘泥于基本要求中的利用数组来实现线性表, 并用线性表来实现约瑟夫环问题,在尝试用链表实现后问题变得简单了些;在插 入元素这一步费不少时间,头尾节点的移动关系也需要理解
四、详细设计
程序代码:
#include <iostream>
using namespace std;
main()
{
int n,m,k,j;
//n 为总人数,m 为出列编号
cin>>n>>m;
int *listArray=new int[n]; //将 n 个人放在大小为 n 的数组中

约瑟夫环(顺序表)

约瑟夫环(顺序表)

test:下标值。本次报数完之后,下一个 值为本单元中存放的值,即下一个 test =
P[test]
#include <stdio.h>// main(){
int i, p[17],test, head; // 设置循环控制变量、数组及两个数组下标指针 for(i=0;i<16;i++
p[i]=i+1; //存放下一个单元的下标值(位置号) p[16]=0; test=0; //起始位置(从哪开始报数) while(test!=p[test]){ // 位置号和该位置的下一位置相同时退出
(位置号) i + 1,即 P[ i ] = i + 1;到最后一个人的时候就循 环到第一个人,设置P[16] =0。
3
P[i] 1 2 3 4 5 6 7 8
0
i
01 2 34 5 6 7
16

head:下标值。由于报到3的倍数的 人要退出,为了保持循环顺序表的形 式,要改变退出的人的前一个的值, 例如:要改变P[1]的值使之变为3。 head用来标识报数的前一个人的下标 值,当报到3的倍数的人退出时,改 变前一个人的单元值为报到3的倍数 的人的单元值,使之保持循环顺序表 的形式。如此下去,当只有一个人的 时候test=p[test]。
指针指向的下一位置
test=p[head]; //记住出列位置
} printf(″\n%5d″,test); // 最后一个出列位置
}
❖ 例:设计一个程序求约瑟夫环的出列顺序。约瑟夫 (Joseph)问题:有17个人按顺时针方向围坐一周 (编号为0~16),从第0号的人开始从1报数,凡报到 3的倍数的人离开圈子,一直数下去,直到最后只剩下 一个人为止,问此人原来的位置是多少号?

(完整word版)C语言约瑟夫环问题

(完整word版)C语言约瑟夫环问题

实验一:约瑟夫环问题一.实验目的:要求设计一个程序模拟约瑟夫环问题过程,求出出列编号序列。

二.实验内容:约瑟夫环问题:设编号为1,2,3,……,n的n(n>0)个人按顺时针方向围坐一圈,每个人持有一个正整数密码.开始时任选一个正整数做为报数上限m,从第一个人开始顺时针方向自1起顺序报数,报到m是停止报数,报m的人出列,将他的密码作为新的m值,从他的下一个人开始重新从1报数。

如此下去,直到所有人全部出列为止。

令n最大值取30。

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

三.实验过程:用一个不带头结点的循环链表来处理Josephu 问题:先构成一个有n个结点的单循环链表,然后由k结点起从1开始计数,计到m时,对应结点从链表中删除,把被删除结点的密码作为新的m值,然后再从被删除结点的下一个结点又从1开始计数,直到最后一个结点从链表中删除算法结束。

#include〈stdio.h>#include<stdlib。

h〉#define MAX_NODE_NUM 30#define TRUE 1#define FALSE 0typedef struct NodeType{ int number;int password;struct NodeType *next;}NodeType;/*创建单向循环链表*/static void CreaList(NodeType **,const int);/*运行”约瑟夫环"问题*/static void StatGame(NodeType **, int);/* 打印循环链表*/static void PrntList(const NodeType *);/*得到一个结点*/static NodeType *GetNode(const int, const int);/*测试链表是否为空,空为TRUE,非空为FALSE */ static unsigned EmptyList(const NodeType *);int main(void){ int n,m;NodeType *pHead=NULL;while(1){printf("输入总的人数n(〈=%d):”,MAX_NODE_NUM);scanf("%d",&n);printf(”初始循环的密码为:”);scanf(”%d”,&m);if(n>MAX_NODE_NUM){printf("数字太大,请重新输入!\n");continue;}elsebreak;}CreaList(&pHead,n);printf("\n打印出原始每个结点的序列号和密码\n"); PrntList(pHead);printf(”\n最终每个结点退出的序列号和密码\n");StatGame(&pHead,m);return 0;}static void CreaList(NodeType **ppHead, const int n) {int i,iCipher;NodeType *pNew, *pCur;for(i=1;i〈=n;i++){printf("第%d个人的密码为:",i);scanf(”%d",&iCipher);pNew=GetNode(i,iCipher);if(*ppHead==NULL){*ppHead=pCur=pNew;pCur->next=*ppHead;}else{pNew-〉next=pCur—〉next;pCur-〉next=pNew;pCur=pNew;}}printf(”已完成结点初始化!\n”);}static void StatGame(NodeType **ppHead, int iCipher){int iCounter,iFlag=1,i=1;NodeType *pPrv, *pCur,*pDel;pPrv=pCur=*ppHead;while(pPrv—〉next!=*ppHead)pPrv=pPrv->next;while(iFlag){for(iCounter=1;iCounter〈iCipher;iCounter++){pPrv=pCur;pCur=pCur->next;}if(pPrv==pCur)iFlag=0;pDel=pCur;pPrv-〉next=pCur-〉next;pCur=pCur-〉next;iCipher=pDel—〉password;printf("第%d个退出的是序列号为%d的人,其密码为:%d\n",i, pDel—>number,pDel-〉password);free(pDel);++i;}*ppHead=NULL;}static void PrntList(const NodeType *pHead){const NodeType *pCur=pHead;if (EmptyList(pHead))return;do{printf("第%d 个人,密码:%d\n”,pCur->number,pCur->password);pCur=pCur—〉next;} while (pCur!=pHead);}static NodeType *GetNode(const int iId,const int iCipher){NodeType *pNew;pNew=(NodeType *)malloc(sizeof(NodeType));if(!pNew){printf("错误,内存不足!\n”);exit(—1);}pNew—>number=iId;pNew-〉password=iCipher;pNew—>next=NULL;return pNew;}static unsigned EmptyList(const NodeType *pHead){if(!pHead){printf(”列表为空!\n”);return TRUE;}return FALSE;}。

约瑟夫问题(循环链表)

约瑟夫问题(循环链表)

约瑟夫问题(循环链表)问题描述:约瑟夫是犹太军队的⼀个将军,在反抗罗马的起义中,他所率领的军队被击溃,只剩下残余的部队40余⼈,他们都是宁死不屈的⼈,所以不愿投降做叛徒。

⼀群⼈表决说要死,所以⽤⼀种策略来先后杀死所有⼈。

于是约瑟夫建议:每次由其他两⼈⼀起杀死⼀个⼈,⽽被杀的⼈的先后顺序是由抽签决定的,约瑟夫有预谋地抽到了最后⼀签,在杀了除了他和剩余那个⼈之外的最后⼀⼈,他劝服了另外⼀个没死的⼈投降了罗马。

1//利⽤循环链表模拟约瑟夫问题,把41个⼈⾃杀的顺序编号输出2 #include<iostream>3 #include<malloc.h>4 #include<string.h>5 #include<stdlib.h>6 #include<stdio.h>7using namespace std;89 typedef struct Node{10int data;11struct Node *next;12 }Node,*LinkList;1314void InitList(LinkList &L){15 L = (LinkList)malloc(sizeof(Node));16if(!L)17 exit(0);18 L->next = NULL;19 }2021 LinkList CreatList(LinkList &L, int n){//尾插法创建单链表22 LinkList r,p;23 r = L;24for(int i = 1; i <= n; i++){25 p = (LinkList)malloc(sizeof(Node));26 p->data = i;27 r->next = p;28 r = p;29 }30 r->next = NULL;31 p->next = L->next;//尾部指向头部,循环链表32return p->next;//返回头结点的头指针(构成循环)33 }3435int main(){36int n = 41;37int m = 3;38 LinkList L,p;39 InitList(L);40 p = CreatList(L,n);41 LinkList temp;42 m %= n;43while(p != p->next){44for(int i = 1;i < m-1; i++){45 p = p->next;46 }47 printf("%d->",p->next->data);48//删除结点49//p->next->next;50 temp = p->next;51 p->next = temp->next;52free(temp);53 p = p->next;54 }55 cout<<p->data;56return0;57 }运⾏结果:关于约瑟夫问题的题⽬:n个⼈围成⼀个圈,每个⼈分别标注为1、2、...、n,要求从1号从1开始报数,报到k的⼈出圈,接着下⼀个⼈⼜从1开始报数,如此循环,直到只剩最后⼀个⼈时,该⼈即为胜利者。

实习报告一:用顺序表实现约瑟夫环

实习报告一:用顺序表实现约瑟夫环

实习报告一:用顺序表实现约瑟夫环题目:用顺序表和循环链表实现约瑟夫环的出列顺序。

班级:06计算机B班姓名:学号:0621121005 完成日期:2008-6-14顺序表实现一、需求分析1.本程序中,需要输入的内容均为整型数,输入完成后以“回车符”作为结束标志。

2.程序以用户和计算机的对话方式执行,即在计算机终端上显示“提示信息”之后,由用户在键盘上输入程序的相关数据。

3.程序执行的命令包括:(1)请输入原始密码m和人数n(n不大于30);(2)请依次输入每个人的密码;(3)屏幕上将依次显示出列者的编号;(4)结束。

4.测试数据:m的初值为20;n=7,7个人的密码依次为:3,1,7,2,4,8,4。

实验结果应该为:6,1,4,7,2,3,5。

二、概要设计要用顺序链表实现上述的功能,需要一个抽象数据类型:顺序表。

1.顺序表数据类型定义:ADT sqlist {数据对象:D={ a i |a i∈elemset,i=1,2,…,n, n≥0}数据关系:R1={ <a i-1,a i> | a i-1,a i ∈D,i=2,3,…,n}基本操作:initlist_sq(&l)操作结果:构造一个空的顺序表l。

}ADT sqlist2.本程序包含一个模块:主程序模块:顺序表抽象数据类型;Int main(){接受命令;处理命令;}三、详细设计1.源程序#include<iostream>using namespace std;#define maxlen 30typedef int elemtype;typedef struct{elemtype elem[maxlen];int length;}sqlist;sqlist joseph;void initlist_sq(sqlist &l){l.length=0;}void jos(int m, int n){cout<<"请依次输入"<<n<<"个密码:";for(;joseph.length<n;joseph.length++)cin>>joseph.elem[joseph.length];//赋密码值cout<<"出列顺序为:";int i=-1;//i为数组下标(下一值为0)for(int k=0;k<n;k++){for(int j=0;j<m;){i=(i+1)%n;if(joseph.elem[i]!=0)j++;}cout<<i+1<<" ";m=joseph.elem[i];joseph.elem[i]=0;}cout<<endl;}void main(){int m,n;//m为密码,n为小孩个数cout<<"请输入初始密码m和人数n(n不大于30):";do{cin>>m>>n;if(n<1||n>30) cout<<"人数不合法,请重输(n不大于30):"<<endl;}while(n<1||n>30);initlist_sq(joseph);// 初始化线性表jos(m,n);}2.函数调用关系:main→jos。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
本次实验运用的是C语言,大一时就学过了,在今后的试验中应该多尝试其他的语言来写程序,提高自己思维的兼容性很重要。
这次的设计让我学到了不少的东西,而且了解到编程在现今诸多行业中应用的重要性以及今后的发展,可以说是受益匪浅,为今后开发相关系统奠定了坚实的理论基础和总结了宝贵的开发经验。
for(int i=0;i<n;i++)
{
L->data[i]=a[i];
}
L->length=n;
}
void InitList(Sqlist G&L)//初始化顺序表
{
L=(Sqlist G)malloc(sizeof(Sqlist));
L->length=0;
}
void DestorPList(Sqlist G&L)//释放顺序表空间
4.当输入要出列的元素大于队列里的元素,这将会提示错误如图:
5.当你的输入出队的序列数有误时将会提示错误
6.当你的要输入的数大于定义的最大值时提示错误如图:
7.当你的要输入的数小于定义的最大值时提示错误如图:
五、实验总结
先后学习了C/C++,对编程语言基本上有一些了解,但在数据结构试验程序设计过程中还是学到了很多。
程序运行后,开始考虑各种BUG,比如输入的数大于数组定义的最大值的时候抑或是数组的数小于应该输入的最小值(比如0),比如输入的要出列的元素大于队列中已有的元素抑或是小于数组中应该出现的元素,比如一些错误输入等等之内的BUG都考虑之后的问题。
然后思考与反思后,发现程序还是有美中不足的地方,算法的核心存在一些不足,比如依次从后往前挪动一个元素的时候存在一些效率上的问题,当元素较多时,效率不高!考虑到可以采用标记法,把出队元素标记为0,以后的出队的时候跳过0,而不是进行挪动,这样程序的效率就大大提高了!
经过两天的设计,在不断翻阅以前资料的情况下,有针对性的复习了C/C++中指针、循环的相关理论知识和vc6.0的基础知识和应用技巧,最后比较成功的完成了本次的设计。
本次设计是运用已学的线性表中顺序表的相关内容,由于以前的指针方面知识没有学好,刚开始时有些措手不及,尤其是运用指针申请动态内存,遇到了不小的麻烦,程序检查时没有错误,但运行不了,经过仔细的思考,终于发现了问题所在,特别高兴。
#include<stdlib.h>
#define MAGSIZE 10//宏替换最大值
tPpedef struct
{
int data[MAGSIZE];
int length;
}Sqlist;
void CreatList(Sqlist G&L,int a[],int n)//创建顺序表
{
L=(Sqlist G)malloc(sizeof(Sqlist));
}
printf("\n");
}
}
void main()
{
Sqlist Gs;
InitList(s);
int a[MAGSIZE];
int n=0;
printf("请键入要输入几个数");
printf("\n");
scanf("%d",&n);
for(int i=0;i<n;i++)
{
a[i]=i+1;
{
free(L);
}
void josephus(Sqlist G&L)//约瑟夫环的核心代码
{
int t=0;
int m=0;
printf("请输入数到几个人出来");
printf("\n");
scanf("%d",&m);
if(m>L->length)
{
printf("没有这么多人呀!╮(╯_╰)╭");
(2)掌握顺序表的存储结构以及基本运算的实现。
成绩评定表
类别
评分标准
分值
得分
合计
上机表现
积极出勤、遵守纪律
主动完成设计任务
30分
程序与报告
程序代码规范、功能正确
报告详实完整、体现收获
70分
备注:
评阅教师:
日期:年月日
试验内容
一、实验目的和要求
1、实验目的:
(1)掌握用VC++上机调试线性表的基本方法;
}
else
{
printf("出列顺序为:");
for(int q=L->length;q>=1;q--)
{
t=(t+m-1)%q;
printf("\n");
printf("\t%d\t",L->data[t]);
for(int j=t+1;j<=q-1;j++)
L->data[j-1]=L->data[j];
3、实验要求:用顺序表实现。
2、设计分析
根据实验要求,采用顺序表来完成本次实验。
实验中定义了两个顺序表,一个用来存储n个人的序号,另一个用来存储n个人的出队顺序及序号。
程序中充分考虑了如果出队的元素大于队列的元素个数时应该有的情况,如果出现这样的错误就提示!否则继续出队!
3、源程序代码
#include<stdi源自.h>计算机科学与工程学院
《算法与数据结构》试验报告[一]
专业班级
10级计算机工程02
试验地点
计算机大楼计工教研室
学生学号
1005080222
指导教师
蔡琼
学生姓名
肖宇博
试验时间
20GG-2-29
试验项目
算法与数据结构
试验类别
基础性()设计性()综合性(√)其它()
试验目的及要求
(1)掌握用VC++上机调试线性表的基本方法;
}
CreatList(s,a,n);
josephus(s);
DestorPList(s);
printf("\n");
}四、测试用例(尽量覆盖所有分支)
1.当输入1,2,3,4。。。。。。n的这些数字范围以内的话,可以得到正确的结果如图:
2.当输入的n比较大的时候的情况如图:
3.当输入序列少,出对数大时:
(2)掌握顺序表的存储结构以及基本运算的实现。
2、实验内容
约瑟夫环问题:设编号为1,2,3,……,n的n(n>0)个人按顺时针方向围坐一圈,m为任意一个正整数。从第一个人开始顺时针方向自1起顺序报数,报到m时停止并且报m的人出列,再从他的下一个人开始重新从1报数,报到m时停止并且报m的人出列。如此下去,直到所有人全部出列为止。要求设计一个程序模拟此过程,对任意给定的m和n,求出出列编号序列。
相关文档
最新文档