c语言 不带头结点的循环链表joseph问题
- 格式:docx
- 大小:14.06 KB
- 文档页数:3
C语⾔⽤循环单链表实现约瑟夫环⽤循环单链表实现约瑟夫环(c语⾔),供⼤家参考,具体内容如下源代码如下,采⽤Dev编译通过,成功运⾏,默认数到三出局。
主函数:main.c⽂件#include <stdio.h>#include "head.h"#include "1.h"int main(){Linklist L;int n;printf("请输⼊约瑟夫环中的⼈数:");scanf("%d",&n);Createlist(L,n);printf("创建的约瑟夫环为:\n");Listtrave(L,n);printf("依次出局的结果为:\n");Solution(L,n);return 0;}head.h⽂件:#include "1.h"#include <stdio.h>#include <stdlib.h>typedef int Elemtype;typedef struct LNode{Elemtype data;struct LNode *next;}LNode,*Linklist;void Createlist(Linklist &L,int n){Linklist p,tail;L = (Linklist)malloc(sizeof(LNode));L->next = L;//先使其循环p = L;p->data = 1;//创建⾸节点之后就先给⾸节点赋值,使得后⾯节点赋值的操作能够循环tail = L;for(int i = 2;i <= n;i++){p = (Linklist)malloc(sizeof(LNode));p->data = i;p->next = L;tail->next = p;tail = p;}printf("已⽣成⼀个长度为%d的约瑟夫环!\n",n);}void Listtrave(Linklist L,int n)//遍历函数{Linklist p;p = L;for(int i = 1;i <= n;i++){printf("%3d",p->data);p = p->next;}printf("\n");}int Solution(Linklist L,int n){Linklist p,s;p = L,s = L;int count = 1;while(L){if(count != 3){count++;p = p->next;//进⾏不等于3时的移位}else{Linklist q;q = p;//⽤q保存p所指的位置,⽅便进⾏节点的删除if(s->next->data == s->data)//当只有⼀个元素的时候{printf("%3d\n",s->data);free(s);return OK;}else//当有两个及两个以上的元素的时候{count = 1;//先将count重置为1printf("%3d",p->data);//再打印出出局的值while(s->next != p){s = s->next;//将s移位到p的前驱节点处}p = p->next;//使p指向⾃⼰的下⼀个节点s->next = p;//进⾏删除free(q);}}}}1.h⽂件:#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0#define INFEASIBLE -1#define OVERFLOW -2运⾏结果:以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
原题:用户输入M,N值,从1至N开始顺序循环数数,每数到M输出该数值,直至全部输出。
写出C程序。
(约瑟夫环问题 Josephus)提示:由于当某个人退出圆圈后,报数的工作要从下一个人开始继续,剩下的人仍然是围成一个圆圈的,可以使用循环表,由于退出圆圈的工作对应着表中结点的删除操作,对于这种删除操作频繁的情况,选用效率较高的链表结构,为了程序指针每一次都指向一个具体的代表一个人的结点而不需要判断,链表不带头结点。
所以,对于所有人围成的圆圈所对应的数据结构采用一个不带头结点的循环链表来描述。
设头指针为p,并根据具体情况移动。
为了记录退出的人的先后顺序,采用一个顺序表进行存储。
程序结束后再输出依次退出的人的编号顺序。
由于只记录各个结点的number值就可以,所以定义一个整型一维数组。
如:int quit[n];n为一个根据实际问题定义的一个足够大的整数。
代码:/******************************************************************** created: 2006/06/14 filename: C:\Documents and Settings\Administrator\桌面\tmpp\josephus.c file path: C:\Documents and Settings\Administrator\桌面\tmpp file base: josephus file ext: c author: A.TNG version: 0.0.1 purpose: 实现 Josephus 环问题用户输入M,N值,从1至N开始顺序循环数数,每数到M输出该数值,直至全部输出。
写出C程序。
(约瑟夫环问题 Josephus)*********************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <malloc.h> /* 结构体和函数声明 */ typedef struct _node_t { int n_num; struct _node_t *next; } node_t; node_t *node_t_create(int n); node_t *node_t_get(node_t **pn, int m); /* 功能函数实现 */ /* * name: node_t_create * params: * n [in] 输入要构造的链表的个数 * return: * 返回构造成功的环形单向链表指针 * notes: * 构造节点数量为 n 的环形单向链表* * author: A.TNG 2006/06/14 17:56 */ node_t * node_t_create(int n) { node_t *p_ret = NULL; if (0 != n) { int n_idx = 1; node_t *p_node = NULL; /* 构造 n 个 node_t */p_node = (node_t *) malloc(n * sizeof(node_t)); if (NULL == p_node) return NULL; else memset(p_node, 0, n * sizeof(node_t)); /* 内存空间申请成功 */ p_ret = p_node; for (; n_idx < n; n_idx++) { p_node->n_num = n_idx; p_node->next = p_node + 1;p_node = p_node->next; } p_node->n_num = n;p_node->next = p_ret; } return p_ret; } /* * name: main * params: * none * return: * int * notes: * main function * * author: A.TNG 2006/06/14 18:11 */ int main() { int n, m; node_t *p_list, *p_iter; n = 20; m = 6; /* 构造环形单向链表 */ p_list =node_t_create(n); /* Josephus 循环取数 */ p_iter = p_list; m %= n; while (p_iter !=p_iter->next) { int i = 1; /* 取到第 m-1 个节点 */ for (; i < m - 1; i++) { p_iter =p_iter->next; } /* 输出第 m 个节点的值 */ printf("%d\n", p_iter->next->n_num); /* 从链表中删除第 m 个节点 */ p_iter->next = p_iter->next->next; p_iter = p_iter->next; } printf("%d\n", p_iter->n_num); /* 释放申请的空间 */ free(p_list); system("PAUSE"); }。
第二章习题与解答一判断题1.线性表的逻辑顺序与存储顺序总是一致的。
2.顺序存储的线性表可以按序号随机存取。
3.顺序表的插入和删除操作不需要付出很大的时间代价,因为每次操作平均只有近一半的元素需要移动。
4.线性表中的元素可以是各种各样的,但同一线性表中的数据元素具有相同的特性,因此是属于同一数据对象。
5.在线性表的顺序存储结构中,逻辑上相邻的两个元素在物理位置上并不一定紧邻。
6.在线性表的链式存储结构中,逻辑上相邻的元素在物理位置上不一定相邻。
7.线性表的链式存储结构优于顺序存储结构。
8.在线性表的顺序存储结构中,插入和删除时,移动元素的个数与该元素的位置有关。
9.线性表的链式存储结构是用一组任意的存储单元来存储线性表中数据元素的。
10.在单链表中,要取得某个元素,只要知道该元素的指针即可,因此,单链表是随机存取的存储结构。
二单选题 (请从下列A,B,C,D选项中选择一项)1.线性表是( ) 。
(A) 一个有限序列,可以为空;(B) 一个有限序列,不能为空;(C) 一个无限序列,可以为空;(D) 一个无序序列,不能为空。
2.对顺序存储的线性表,设其长度为n,在任何位置上插入或删除操作都是等概率的。
插入一个元素时平均要移动表中的()个元素。
(A) n/2 (B) n+1/2 (C) n -1/2 (D) n3.线性表采用链式存储时,其地址( ) 。
(A) 必须是连续的;(B) 部分地址必须是连续的;(C) 一定是不连续的;(D) 连续与否均可以。
4.用链表表示线性表的优点是()。
(A)便于随机存取(B)花费的存储空间较顺序存储少(C)便于插入和删除(D)数据元素的物理顺序与逻辑顺序相同5.某链表中最常用的操作是在最后一个元素之后插入一个元素和删除最后一个元素,则采用( )存储方式最节省运算时间。
(A)单链表(B)双链表(C)单循环链表(D)带头结点的双循环链表6.循环链表的主要优点是( )。
(A)不在需要头指针了(B)已知某个结点的位置后,能够容易找到他的直接前趋(C)在进行插入、删除运算时,能更好的保证链表不断开(D)从表中的任意结点出发都能扫描到整个链表7.下面关于线性表的叙述错误的是( )。
向量法求解Josephus问题智能一班林潇 2220101468一.实验题目描述Josephus问题可描述如下:设有n个人围成一个环,现从第s个人开始报数,数到第m的人出列,然后从出列的下一个人从新开始报数,数到第m的人又出列,如此重复,直至所有人均出列为止。
求这些人出列的顺序。
二.实验目的熟练掌握线性表的链表实现基本操作。
三.实现功能以循环单链表为存储结构,求解Josephus问题。
四.算法步骤编写一个独立的函数模块求解Josephus问题,该函数仅通过参数与外界进行数据交换,不使用其它非局部变量,实现方案应具有良好的健壮性。
另编写一个主函数作为驱动,在主函数中处理数据的输入与输出。
五.程序结构描述程序主要包括一个驱动功能的主函数,包括要排列数组元素的输入,开始报数的位置,所报数字的输入。
还有一个独立函数模块来实现Josephus问题,主函数通过调用该函数来实现元素的出列,并将出列元素按顺序重新存入数组,并将出列元素按顺序输出。
六.程序代码#define N 10#include<stdlib.h>#include<stdio.h>typedef struct LNode{//建立节点类型int message;struct LNode *next;}LNode,*LinkList;void Josephus(LinkList L,int s,int m,int n,int e,int a[]);void main(){int i,s,m,e;int a[10];printf("请输入Josephus环的元素");//输入组成Josephus环的元素for(i=0;i<10;i++)scanf("%d",&a[i]);printf("请输入开始报数位置及所报数字");//输入开始报数位置及所报数字scanf("%d %d",&s,&m);LinkList L;//建立单循环连的头结点L=(LinkList)malloc(sizeof(LNode));L->message=a[0];L->next=NULL;Josephus(L,s,m,N,e,a);}void Josephus(LinkList L,int s,int m,int n,int e,int a[]){ LinkList p,q;int i,j;//将组成Josephus环的元素储存到单链中for(i=n-1;i>0;i--){p=(LinkList)malloc(sizeof(LNode));p->message=a[i];p->next=L->next;L->next=p;}LinkList H;H=L;for(i=0;i<n-1;i++)H=H->next;H->next=L;//尾部节点的指针指向头结点p=L;for(i=1;i<s;i++)p=p->next;//找到开始报数位置i=1;//利用循环将元素输出while(p->next!=p->next->next){for(j=1;j<m-1;j++)p=p->next;q=p->next;p->next=q->next;e=q->message;free(q);//释放被输出元素的节点printf("\n第%d 个出列的元素为%d\n",i,e);p=p->next;i++;}printf("\n第%d 个出列的元素为%d\n",10,p->message);}七.测试数组及结果测试数组为一个长度为10的整形数组,存储元素为1-10是个整数。
C语言的循环链表和约瑟夫环C语言的循环链表和约瑟夫环约瑟夫问题)是一个数学的应用问题,对于学习C语言四非常挺有帮助的,下面是店铺为大家搜集整理出来的有关于C语言的循环链表和约瑟夫环,一起了解下吧!循环链表的实现单链表只有向后结点,当单链表的尾链表不指向NULL,而是指向头结点时候,形成了一个环,成为单循环链表,简称循环链表。
当它是空表,向后结点就只想了自己,这也是它与单链表的主要差异,判断node->next是否等于head。
代码实现分为四部分:1. 初始化2. 插入3. 删除4. 定位寻找代码实现:1 2 3 4 5 6 7 8 9 1 0 1 1 1 2 1 3 1void ListInit(Node *pNode){int item;Node *temp,*target;cout<<"输入0完成初始化"<<endl; cin="">>item;if(!item)return ;if(!(pNode)){ //当空表的时候,head==NULLpNode = new Node ;if(!(pNode))exit(0);//未成功申请pNode->data = item;pNode->next = pNode;}else{//for(target = pNode;target->next!=pNode;target = target->next);4 15 16 17 18 19 2 0 2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 2 9 3 0 3 1 3 2 3 3 3 4 3 5 3temp = new Node;if(!(temp))exit(0);temp->data = item;temp->next = pNode;target->next = temp;}}}void ListInsert(Node *pNode,int i){ //参数是首节点和插入位置Node *temp;Node *target;int item;cout<<"输入您要插入的值:"<<endl; cin="">>item;if(i==1){temp = new Node;if(!temp)exit(0);temp->data = item;for(target=pNode;target->next != pNode;target = target->next);temp->next = pNode;target->next = temp;pNode = temp;}else{target = pNode;for (int j=1;j<i-1;++j) target="target-">next;temp = new Node;if(!temp)exit(0);temp->data = item;temp->next = target->next;target->next = temp;}}void ListDelete(Node *pNode,int i){Node *target,*temp;if(i==1){for(target=pNode;target->next!=pNode;target=target ->next);temp = pNode;//保存一下要删除的首节点 ,一会便于释放6 37 38 39 4 0 4 1 4 2 4 3 4 4 4 5 4 6 4 7 4 8 4 9 5 0 5 1 5 2 5 3 5 4 5 5 5 6 5 7 5pNode = pNode->next;target->next = pNode;temp;}else{target = pNode;for(int j=1;j<i-1;++j) target="target-">next;temp = target->next;//要释放的nodetarget->next = target->next->next;temp;}}int ListSearch(Node *pNode,int elem){ //查询并返回结点所在的位置Node *target;int i=1;for(target = pNode;target->data!=elem && target->next!= pNode;++i)target = target->next;if(target->next == pNode && target->data!=elem)return 0;else return i;}</i-1;++j)></i-1;++j)></endl;></endl;>5 96 0 6 1 6 2 6 3 6 4 6 5 6 6 67 68 69 7 0 7 1 7 2 7 3 7 4 7 5 7 6 7 7 7 8 7 9 8约瑟夫问题约瑟夫环(约瑟夫问题)是一个数学的'应用问题:已知n个人(以编号1,2,3…n分别表示)围坐在一张圆桌周围。
循环链表范例Josephus问题⼀群⼩孩围成⼀圈,任意假定⼀个数N,从第⼀个⼩孩起,逆时针⽅向数,每数到第M个⼩孩时,该⼩孩就离开,然后再由下⼀个重新报数,⼩孩不断离开,圈⼦不断缩⼩。
最后,剩下的⼀个⼩孩便是胜利者。
究竟胜利者是第⼏个⼩孩呢?类似这样的问题都叫Josephus(约瑟夫斯)问题。
我们可以⽤⼀个循环链表表⽰排成圆圈的⼈,整数i代表第i个⼈,先为1号建⽴⼀个单节点循环链表,再把2号到N号依次插⼊到1号节点后⾯,这样就形成了⼀个由1--N(逆时针)的员,最后x指向N,然后我们从1号开始跳过M-1个节点,把第M-1个节点的链接改为指向第M+1号节点,⼀直这样做,直到只剩下⼀个节点为⽌。
#include<iostream>using namespace std;typedef int T;struct node{T data;struct node *next;node(T x,node *t):data(x),next(t) { }};typedef struct node *Link;int main(){int i, N,M;cin>>N>>M;Link t=new node(1,0);t->next=t;Link x=t;for(i=2;i<=N;i++)x=(x->next=new node(i,t));while(x!=x->next){for(i=1;i<M;i++) x=x->next;x->next=x->next->next;}cout<<x->data<<endl;}递推思路:本思路可⽤O(n)的复杂度解决最原始的Josephus问题,即只找出最后⼀个幸免者。
关于约瑟夫(Josephus)问题:N个⼈围成⼀圈,从第⼀个开始报数,第M个将被杀掉,最后剩下⼀个,其余⼈都将被杀掉。
约瑟夫问题C代码 1/*Joseph Problem2 *利⽤单循环链表解决约瑟夫问题。
3 *问题描述:将n个数链接成⼀个环,从第m个开始,每次从1计数到s时4 * 将s删除。
从下⼀个开始再次从1计数⾄s时删除s。
直到全5 * 部删除为⽌。
6 * */7 #include<stdio.h>8 #include<stdlib.h>910 typedef struct Node{11int data;12struct Node* next;13 }Node;14 typedef struct Node* LinkList;1516void CreateJosephLoop(LinkList *L,int number){17//创建Joseph环,在头结点中放⼊了元素1.18 *L = (LinkList)malloc(sizeof(struct Node));19if(!(*L)){20 printf("Error:malloc:0!\n");21 exit(1);22 }23 (*L)->next = (*L);24 (*L)->data = 1;25int i;26 LinkList new;27 LinkList tail = *L;28for(i = 1; i < number; i++){29new = (LinkList)malloc(sizeof(struct Node));30if(!new){31 printf("Error:malloc:1+i");32 exit(1);33 }34new->data = i+1;35new->next = tail->next;36 tail->next = new;37 tail = new;38 }39 }40void JosephProblem(int loopSize,int from,int stepBy){41//loopSize:Joseph环的⼤⼩42//form:从from开始43//stepBy:每次计数到stepBy时删除stepBy所指向的元素44 LinkList L;45 CreateJosephLoop(&L,loopSize);46int seekStart = 1;47while(seekStart < from){48 L = L->next;49 seekStart += 1;50 }51while(L->data != L->next->data){52int i = 1;53 LinkList temp;54for(i = 1;i < stepBy - 1; ){55 L = L->next;56 i++;57 }58 temp = L->next;59 printf("%d-->",temp->data);60 L->next = L->next->next;61 L = L->next;62free(temp);63 }64 printf("%d\n",L->data);65 }66int main(){67 JosephProblem(10,3,4);68 JosephProblem(41,1,3); 69return0;70 }。
C语⾔基于循环链表解决约瑟夫环问题的⽅法⽰例本⽂实例讲述了C语⾔基于循环链表解决约瑟夫环问题的⽅法。
分享给⼤家供⼤家参考,具体如下:概述:约瑟夫环问题,是⼀个经典的循环链表问题,题意是:已知 n 个⼈(以编号1,2,3,…,n分别表⽰)围坐在⼀张圆桌周围,从编号为 k 的⼈开始顺时针报数,数到 m 的那个⼈出列;他的下⼀个⼈⼜从 1 还是顺时针开始报数,数到 m 的那个⼈⼜出列;依次重复下去,要求找到最后出列的那个⼈。
例如有 5 个⼈,要求从编号为 3 的⼈开始,数到 2 的那个⼈出列:出列顺序依次为:编号为 3 的⼈开始数 1,然后 4 数 2,所以 4 先出列;4 出列后,从5 开始数 1,1 数 2,所以 1 出列;1 出列后,从2 开始数 1,3 数 2,所以 3 出列;3 出列后,从 5 开始数 1,2 数 2,所以 2 出列;最后只剩下 5 ⾃⼰,所以 5 出列。
代码实现:#include <stdio.h>#include <stdlib.h>typedef struct node{int number;struct node * next;}person;person * initLink(int n){person * head=(person*)malloc(sizeof(person));head->number=1;head->next=NULL;person * cyclic=head;for (int i=2; i<=n; i++) {person * body=(person*)malloc(sizeof(person));body->number=i;body->next=NULL;cyclic->next=body;cyclic=cyclic->next;}cyclic->next=head;//⾸尾相连return head;}void findAndKillK(person * head,int k,int m){person * tail=head;//找到链表第⼀个结点的上⼀个结点,为删除操作做准备while (tail->next!=head) {tail=tail->next;}person * p=head;//找到编号为k的⼈while (p->number!=k) {tail=p;p=p->next;}//从编号为k的⼈开始,只有符合p->next==p时,说明链表中除了p结点,所有编号都出列了,while (p->next!=p) {//找到从p报数1开始,报m的⼈,并且还要知道数m-1de⼈的位置tail,⽅便做删除操作。
数据结构—约瑟夫环问题(循环单链表)n个数据元素构成⼀个环,从环中任意位置开始计数,计到m将该元素从表中取出,重复上述过程,直⾄表中只剩下⼀个元素。
解题思路:⽤⼀个⽆头结点的循环单链表来实现n个元素的存储。
循环单链表:尾指针指向头结点。
这样指针可以循环移动。
可以使⽤两个指针来操作,将指针q指向需要操作的结点上,指针p指向需要操作结点的前⼀个结点。
1 #include <stdio.h>2 #include <stdlib.h>3 #include <malloc.h>4 #include <math.h>5#define NULL 06 typedef struct LNode7 {8int num;///编号9struct LNode *next;10 } LNode, *Linklist;11 Linklist head,tail;12void Createlist(int n)///创建含有n个结点的单循环链表13 {14int i;15 Linklist p,q;16 head=(Linklist)malloc(sizeof(LNode));17 q=head;18 q->num=1;19for(i=2; i<=n; i++)20 {21 p=(Linklist)malloc(sizeof(LNode));22 p->num=i;23 q->next=p;24 q=p;25 }26 p->next=head;27 tail=p;///尾指针要指向头结点28 }29void Outlist(int k)30 {31int i;32 Linklist p,q;33 p = head;34for(i=1; i<k-1; i++)///循环k-2次35 {36 p = p->next;///指向需要操作元素的前⼀个指针37 }38 q = p->next;///指向需要操作元素的指针39while(q != p)40 {41 printf("%3d",q->num);42 p->next = q->next;///删除q所指向的元素43for(i=1; i<k; i++)///因为要经过已经删除的元素,所以需要多删除⼀次44 {45 p = p->next;46 }47 q = p->next;48 }49 printf("%3d\n",q->num);5051 }52int main()53 {54int k,n;55 printf("---------------约瑟夫环问题--------------\n");56 printf("\n请输⼊总⼈数和从第⼏个⼈开始报数n,k:\n");57 scanf("%d%d",&n,&k);58 Createlist(n);59 printf("\n出队的次序:\n");60 Outlist(k);61return0;62 }我看了⼀下我同学的做法,可以p直接使⽤尾指针,⽽q来⾃头指针,这样在遍历的时候,p指针⼀直会在q指针之前。
Josephu约瑟夫问题java实现(环形链表)5.4.1约瑟夫问题Josephu(约瑟夫、约瑟夫环) 问题为:设编号为 1,2,… n 的 n 个⼈围坐⼀圈,约定编号为 k(1<=k<=n)的⼈从 1 开始报数,数 到 m 的那个⼈出列,它的下⼀位⼜从 1 开始报数,数到 m 的那个⼈⼜出列,依次类推,直到所有⼈出列为⽌,由 此产⽣⼀个出队编号的序列。
5.4.2解决思路⽤⼀个不带头结点的循环链表来处理 Josephu 问题:先构成⼀个有 n 个结点的单循环链表,然后由 k 结点起从 1 开 始计数,计到 m 时,对应结点从链表中删除,然后再从被删除结点的下⼀个结点⼜从 1 开始计数,直到最后⼀个 尚硅⾕ Java 数据结构和算法 更多 Java –⼤数据 –前端 –python ⼈⼯智能 -区块链资料下载,可访问百度:尚硅⾕官⽹ 第 55页 结点从链表中删除算法结束。
代码实现//约瑟夫问题-环形链表public class Josepfu {public static void main(String[] args) {CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList();circleSingleLinkedList.addBoy(5);// 加⼊ 5 个⼩孩节点circleSingleLinkedList.showBoy();circleSingleLinkedList.countBoy(1, 2, 5);}}//环形链表class CircleSingleLinkedList{//指向链表的第⼀个节点private Boy first = null;//添加num个⼩孩节点public void addBoy(int num){if (num<1)throw new RuntimeException("输⼊值错误");Boy curBoy = null;for(int i=1;i<=num;i++){Boy boy = new Boy(i);if (i==1){first = boy;first.setNext(first);//形成环curBoy = first;}else{boy.setNext(first);curBoy.setNext(boy);curBoy = boy;}}}// 根据⽤户的输⼊,计算出⼩孩出圈的顺序/**** @param startNo* 表⽰从第⼏个⼩孩开始数数* @param countNum* 表⽰数⼏下* @param nums* 表⽰最初有多少⼩孩在圈中*/public void countBoy(int startNo, int countNum, int nums) {if (nums<1||countNum<1||first==null||startNo<1||startNo>nums)throw new RuntimeException("参数有误,从新输⼊!!");//创建辅助指针,指向环形链表的最后⼀个节点Boy helper = first;while (helper.getNext()!=first){helper = helper.getNext();}//移动helper和first,使从第startNo个⼩孩开始数for (int i=0;i<(startNo-1);i++){helper = helper.getNext();first = first.getNext();}//开始数数,出圈while (helper!=first){//报数for (int i=0;i<(countNum-1);i++){helper = helper.getNext();first = first.getNext();}System.out.println("⼩孩"+ first.getNo() +"出队列:" );first = first.getNext();helper.setNext(first);}System.out.println("最后的⼩孩:"+ first.getNo());}//遍历环形链表public void showBoy(){if (first==null)throw new RuntimeException("链表为空");System.out.println("⼩孩的编号: "+first.getNo());//first⽆法移动,创建中介节点遍历链表Boy curBoy = first.getNext();//当中介节点再⼀次回到first时,表⽰链表遍历完成while (curBoy!=first){System.out.println("⼩孩的编号: "+curBoy.getNo()); curBoy = curBoy.getNext();}}}//创建boy类表⽰⼀个节点class Boy{private int no;private Boy next;public Boy(int no) {this.no = no;}public int getNo() {return no;}public void setNo(int no) {this.no = no;}public Boy getNext() {return next;}public void setNext(Boy next) {this.next = next;}}。
Josephu(约瑟夫)问题解析Josephu问题为:设置编号为1,2,3,......n的n个⼈围坐⼀圈,约定编号为k(1<=k<=n)的⼈从1看是报数,数到m的那个⼈出列,它的下⼀位⼜从1开始报数,数到m的那个⼈出列,以此类推,直到所有⼈出列为⽌,由此产⽣⼀个出队编号的序列。
提⽰:⽤有个不带头的循环链表来处理Josephu问题:先构成⼀个有n个结点的单循环链表,然后由k结点起从1开始计数,计到m时,对应结点从链表中删除,然后再从被删除结点的下⼀个结点⼜从1开始计数,直到最后⼀个结点从链表中删除算法结束。
代码:public class Demo{public static void main(String[] args){CycLink cyclink=new CycLink();cyclink.setLen(5);cycLink.createLink();cyclink.show();}}//⼩孩class Child{//编号int no;//结点Child nextChild=null;public Child(int no){//给编号this.no=no;}}//环形链表class CycLink{//先定义⼀个指向链表第⼀个⼩孩的引⽤//指定第⼀个⼩孩的引⽤不能动,不然以后找不到他了Child firstChild=null;//定义⼀个游标Child temp=null;//表⽰共有⼏个⼩孩int len=0;//设置链表⼤⼩public void setLen(int len){this.len=len;}//初始化环形链表public void createLink(){for(int i=1;i<=len;i++){if(i==1){//创建第⼀个⼩孩Child ch=new Child(i);this.firstChild=ch;this.temp=ch;}else{//创建最后⼀个⼩孩if(i==len){Child ch=new Child(i);temp.nextChild=ch;temp=ch;temp.nextChild=this.firstChild;}else{//继续创建⼩孩Child ch=new Child(i);//连接,搭桥temp.nextChild=ch;//temp向前⾛⼀步,指向刚刚进来的孩⼦temp=ch;}}}}//打印该环形链表public void show(){Child temp=this.firstChild;do{System.out.println(temp.no);temp=temp.nextChild;}while(temp!=this.fistChild);}}优化:代码:public class Demo{public static void main(String[] args){CycLink cyclink=new CycLink();cyclink.setLen(50);cycLink.createLink();cycLink.setK(2);cycLink.setM(3);cyclink.show();cyclink.play();}}//⼩孩class Child{//编号int no;//结点Child nextChild=null;public Child(int no){//给编号this.no=no;}}//环形链表class CycLink{//先定义⼀个指向链表第⼀个⼩孩的引⽤//指定第⼀个⼩孩的引⽤不能动,不然以后找不到他了 Child firstChild=null;//定义⼀个游标Child temp=null;//表⽰共有⼏个⼩孩int len=0;int k=0;int m=0;//设置mpublic void setM(int m){this.m=m;}//设置链表⼤⼩public void setLen(int len){this.len=len;}//设置从第⼏个⼈开始数数public void setK(int k){this.k=k;}//开始playpublic void play(){Child temp=this.fistChild;//1.先找到开始数数的⼈//int i=1;i<k;因为⾃⼰也要数⼀下,所以i不能为k for(int i=1;i<k;i++){temp=temp.nexChild;}while(this.len!=1){//2.数m下for(int j=1;j<m;j++){temp=temp.nextChild;}//找到要出圈的前⼀个⼩孩,有待优化Child temp2=temp;while(temp2.nextChild!=temp){temp2=temp2.nextChild;}//3.将数到m的⼩孩,退出圈temp2.nextChild=temp.nextChild;//让temp指向数数的⼩孩temp=temp.nextChild;this.len--;}//最后⼀个⼩孩(验证)System.out.println(temp.no);}//初始化环形链表public void createLink(){for(int i=1;i<=len;i++){if(i==1){//创建第⼀个⼩孩Child ch=new Child(i);this.firstChild=ch;this.temp=ch;}else{//创建最后⼀个⼩孩if(i==len){Child ch=new Child(i);temp.nextChild=ch;temp=ch;temp.nextChild=this.firstChild;}else{//继续创建⼩孩Child ch=new Child(i);//连接,搭桥temp.nextChild=ch;//temp向前⾛⼀步,指向刚刚进来的孩⼦ temp=ch;}}}}//打印该环形链表public void show(){Child temp=this.firstChild;do{System.out.println(temp.no);temp=temp.nextChild;}while(temp!=this.fistChild);}}。
1)内容:约瑟夫(Joseph)问题的一种描述是:编号为1,2,..., n 的n 个人按顺时针方向围坐一圈, 每人持有一个密码(正整数)。
一开始选任一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止报数。
报m的人出列,将它的密码作为新的m值,再从下个人开始新一轮报数,如此反复,直到剩下最后一人则为获胜者。
试设计一个程序求出出列顺序。
2)要求:利用单向循环链表存储结构模拟此过程,按照出列的顺序印出各人的编号。
3) 测试数据: n=7,7 个人的密码依次为:3,1,7,2,4,8,4 。
m的初值为20,则正确的出列顺序应为6,1,4,7,2,3,5。
完整代码:#include<stdio.h>#include<stdlib.h>struct person{int num;int order;struct person *next;};static struct person *head=NULL;struct person *CreatList(void){struct person *rear;struct person *p;int k=0;while(1){p=(struct person*)malloc(sizeof(struct person));p->order=++k;printf("\n请输入一个人所持的密码,输入0则建表结束:");scanf("%d",&p->num);if(p->num==0)break;if(head==NULL) head=p;else rear->next=p;rear=p;}if(rear!=NULL) rear->next=head;printf("\n建表结束\n");return head;}void josephus(struct person *p,int m) {int i,k;struct person* r;if(m==1)p=p->next;else{for(i=2;i<m;i++)p=p->next;}r=p->next;k=r->num;printf("%d ",k);printf("%d\n",r->order);p->next=r->next;free(r);if(p!=p->next)josephus(p->next,k);else{printf("%d ",p->num);printf("%d\n",p->order);}}void main(){int m;struct person *pos;CreatList();printf("请输入初始值m:");scanf("%d",&m);printf("密码顺序\n");pos=head;josephus(pos,m);}/* 测试数据,复制粘贴可用3172 4 8 4 0 20 */。
循环链表josephus问题#include#include#define NULL 0int n;struct people{int num;struct people *next;};struct people *creat(){int i;int length = 0;struct people *p1,*p2,*head;printf("输入总人数n:");scanf("%d",&n);if(n==1||n==0)head=NULL; //当输入为0或者1时不符合要求,head 赋值为NULLelse{for(i=1;i<=n;i++){if(i==1){head = p1 = p2 = (struct people *)malloc(sizeof(struct people)); //创建第一个节点head->num=1; //将第一个节点赋值为1}else{p1 = (struct people *)malloc(sizeof(struct people)); //创建下一个节点p1->num=i;p2->next = p1; //将前一个节点与刚创建的节点连起来p2 = p1; //p2指针后移}length++;}p1->next=head; //将最后一个节点与第一个结点连起来printf("链表长度为:%d\n",length);}return head;}void print(struct people *head){struct people *p;p=head;printf("人的号数依次为:");do{printf("%d ",p->num);p=p->next;}while(p!=head); //输出p指向节点的值并将其后移一位,直到p 再次等于head指针}struct people *seek(struct people *head){int s,i;struct people *p=head;printf("\n输入想要从第几个人开始报数:");scanf("%d",&s);for(i=1;i<s;i++)< p="">p=p->next; //将p指针从head向后移s-1位printf("第%d个人为:%d号\n",i,p->num);return p;}void del(struct people *head){int i,j,m;struct people *p1,*p2;p1=p2=seek(head);printf("输入数到几的人出列:");scanf("%d",&m);for(i=1;i<=n;i++){for(j=1;j<m;j++)< p="">{p1=p2;p2=p2->next;} //将p2的值赋给p1然后将p2后移一位p1->next=p2->next; //将p2所指向的节点的前后两节点连接if(i<n)< p="">printf("第%d个出列的人为:%d号\n",i,p2->num);elseprintf("最后剩下的人为:%d号\n",p2->num);p2=p1->next; //使p2指向被删除节点的下一个节点}}void main(){struct people *head;printf("**********~-~josehus~-~**********\n"); head=creat();if(head==NULL)printf("error!\n");else{print(head);del(head);}}</n)<></m;j++)<></s;i++)<>。
Joseph问题——C语⾔实现Joseph问题题⽬描述:原始的Joseph问题的描述如下:有n个⼈围坐在⼀个圆桌周围,把这n个⼈依次编号为1,…,n。
从编号是start的⼈开始报数,数到第num 个⼈出列,然后从出列的下⼀个⼈重新开始报数,数到第num个⼈⼜出列,…,如此反复直到所有的⼈全部出列为⽌。
⽐如当n=6,start=1,num=5的时候,出列的顺序依次是5,4,6,2,3,1。
C语⾔程序:这是⽤不带头结点的循环链表实现的#include<stdio.h>#include<stdlib.h>typedef struct node{int data;struct node *link;}LNode,*LinkList;int main(){LinkList p,r,list=NULL;int i,n,num,start;//此处n是指所有⼈数//此处start是指从编号为start的⼈开始报数//此处num是指数到num的⼈出列scanf("%d%d%d",&n,&num,&start);for(i=1;i<=n;i++){p=(LinkList)malloc(sizeof(LNode));p->data=i;if(list==NULL)list=p;elser->link=p;r=p;}p->link=list;p=list;//以上是构建了⼀个循环链表,链表不带头结点for(i=1;i<start;i++){r=p;p=p->link;}//以上是得到了起始编号start的指针p,其前缀指针为rwhile(p->link!=p){for(i=1;i<num;i++){r=p;p=p->link;}//此时p是应当被删除的⼀位,r是p的前缀指针r->link=p->link;printf("%d ",p->data);free(p);p=r->link;}printf("\n最后被删除的结点是%d\n",p->data);}这是我实现的程序,因为感觉⽹上的函数都是封装起来的,所以就⾃⼰实现了⼀遍不⽤函数封装的程序,也是很普通的做法,仅供初学者看看吧~~。
向量法求解Josephus问题智能一班林潇 2220101468一.实验题目描述Josephus问题可描述如下:设有n个人围成一个环,现从第s个人开始报数,数到第m的人出列,然后从出列的下一个人从新开始报数,数到第m的人又出列,如此重复,直至所有人均出列为止。
求这些人出列的顺序。
二.实验目的熟练掌握线性表的链表实现基本操作。
三.实现功能以循环单链表为存储结构,求解Josephus问题。
四.算法步骤编写一个独立的函数模块求解Josephus问题,该函数仅通过参数与外界进行数据交换,不使用其它非局部变量,实现方案应具有良好的健壮性。
另编写一个主函数作为驱动,在主函数中处理数据的输入与输出。
五.程序结构描述程序主要包括一个驱动功能的主函数,包括要排列数组元素的输入,开始报数的位置,所报数字的输入。
还有一个独立函数模块来实现Josephus问题,主函数通过调用该函数来实现元素的出列,并将出列元素按顺序重新存入数组,并将出列元素按顺序输出。
六.程序代码#define N 10#include<stdlib.h>#include<stdio.h>typedef struct LNode{//建立节点类型int message;struct LNode *next;}LNode,*LinkList;void Josephus(LinkList L,int s,int m,int n,int e,int a[]);void main(){int i,s,m,e;int a[10];printf("请输入Josephus环的元素");//输入组成Josephus环的元素for(i=0;i<10;i++)scanf("%d",&a[i]);printf("请输入开始报数位置及所报数字");//输入开始报数位置及所报数字scanf("%d %d",&s,&m);LinkList L;//建立单循环连的头结点L=(LinkList)malloc(sizeof(LNode));L->message=a[0];L->next=NULL;Josephus(L,s,m,N,e,a);}void Josephus(LinkList L,int s,int m,int n,int e,int a[]){ LinkList p,q;int i,j;//将组成Josephus环的元素储存到单链中for(i=n-1;i>0;i--){p=(LinkList)malloc(sizeof(LNode));p->message=a[i];p->next=L->next;L->next=p;}LinkList H;H=L;for(i=0;i<n-1;i++)H=H->next;H->next=L;//尾部节点的指针指向头结点p=L;for(i=1;i<s;i++)p=p->next;//找到开始报数位置i=1;//利用循环将元素输出while(p->next!=p->next->next){for(j=1;j<m-1;j++)p=p->next;q=p->next;p->next=q->next;e=q->message;free(q);//释放被输出元素的节点printf("\n第%d 个出列的元素为%d\n",i,e);p=p->next;i++;}printf("\n第%d 个出列的元素为%d\n",10,p->message);}七.测试数组及结果测试数组为一个长度为10的整形数组,存储元素为1-10是个整数。
循环队列之约瑟夫环问题约瑟夫问题 约瑟夫环(约瑟夫问题)是⼀个数学的应⽤问题:已知n个⼈(以编号1,2,3...n分别表⽰)围坐在⼀张圆桌周围。
从编号为k的⼈开始报数,数到m的那个⼈出列;他的下⼀个⼈⼜从1开始报数,数到m的那个⼈⼜出列;依此规律重复下去,直到圆桌周围的⼈全部出列。
通常解决这类问题时我们把编号从0~n-1,最后结果+1即为原问题的解。
循环队列求解(链式)#include<stdio.h>#include<stdlib.h>//循环队列//typedef int ElemType;typedef struct QueueNode{int data;struct QueueNode *next;}QueueNode;typedef struct Queue{QueueNode *front;QueueNode *rear;}Queue;void InitQueue(Queue *q){q->front=q->rear=NULL;}void EnQueue(Queue *q , int value){QueueNode *temp=(QueueNode*)malloc(sizeof(QueueNode));temp->data=value;if(q->rear==NULL){temp->next=temp;q->rear=q->front=temp;}else{temp->next=q->rear->next;q->rear->next=temp;q->rear=temp;}}//enter a element from the tailvoid DeQueue(Queue *q, int *value){QueueNode *temp=(QueueNode*)malloc(sizeof(QueueNode)); if(q->rear==NULL){return;}// It's nullelse if(q->rear->next==q->rear){*value=q->front->data;free(q->rear);q->rear=q->front=NULL;}//It just has one nodeelse{*value=q->front->data;temp=q->front;q->front=temp->next;q->rear->next=q->front;}//more one nodefree(temp);}//delete a element from the headint main(){Queue *q=(Queue*)malloc(sizeof(Queue));int i,m,n,count,temp;printf("请输⼊⼈数n和循环要报的数m(两数之间留个空格)\n"); scanf("%d%d",&n,&m);for(i=1;i<=n;i++)EnQueue(q,i);printf("出圈序列:\n");while(q->front){ count=1;while(count<m){q->front=q->front->next;q->rear=q->rear->next;count++;}count=1;DeQueue(q,&temp);printf("%d ",temp);}putchar('\n');}简单解法#include <stdio.h>int josephus(int n, int m) {if(n == 1) {return0;}else {return (josephus(n-1, m) + m) % n;}}int main() {int n, m;while (scanf("%d", &n) == 1) {if (!n) {break;}scanf("%d", &m);int result = josephus(n, m);printf("%d\n", result+1);}return0;}。