c语言 不带头结点的循环链表joseph问题
C语言用循环单链表实现约瑟夫环

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运⾏结果:以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
约瑟夫环问题(Josephus)源代码讲解

原题:用户输入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"); }。
数据结构C语言版部分习题及答案[2]
![数据结构C语言版部分习题及答案[2]](https://img.taocdn.com/s3/m/e044a021e87101f69e319522.png)
第二章习题与解答一判断题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问题

向量法求解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语言四非常挺有帮助的,下面是店铺为大家搜集整理出来的有关于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问题

循环链表范例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代码

约瑟夫问题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语⾔基于循环链表解决约瑟夫环问题的⽅法⽰例本⽂实例讲述了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,⽅便做删除操作。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
listnode *head = CreatCycleList(5);
Display(head);
listnode *p = Joseph(head, 8, 3);
printf("%d\n",p->data);
return 0;
}
以下是不带头结点的循环链表算法
*/
#include <stdio.h>
#include <stdlib.h>
typedef int data_t;
typedef struct node
{
data_t data;
struct node *next;
}listnode, *linklist;
/*创建一个不带头节点的循环链表*/
/*
Joseph问题
题目描述:
原始的Joseph问题的描述如下:有n个人围坐在一个圆桌周围,把这n个人依次编号为1,…,n。从编号是start的人开始报数,数到第num个人出列,然后从出列的下一个人重新开始报数,数到第num个人又出列,…,如此反复直到所有的人全部出列为止。比如当n=6,start=1,num=5的时候,出列的顺序依次是5,4,6,2,3,1。
}
return p;
}
void Display(listnode *head)
{
listnode *p = head;
while(p->next != head)
{
printf("%d,",p->data);
p = p->next;
}
printf("%d\n",p->data);
}
int main(int argc, char *argv[])
{
int i;
listnode *p, *q;//p遍历链表,q指向待宰的人
p = head;
/*找位置,p最后停在开始报数的前一个p->next != head)
{
p = p->next;
}
}
else
{
for(i = 1; i < start-1; i++)
{
p = p->next;
}
}
/*开杀*/
while(p != p->next)
{
for(i = 1; i < killNum; i++)
{
p = p->next;
}
q = p->next;
p->next = q->next;
printf("%d,",q->data);
free(q);
q = NULL;
p = head;
while(i <= num)
{
q = (listnode*)malloc(sizeof(listnode));
q->data = i;
q->next = NULL;
p->next = q;
p = q;
i++;
}
p->next = head;
return head;
}
listnode* Joseph(listnode *head, int start, int killNum)
listnode* CreatCycleList(int num)
{
int i = 2;
listnode *head = NULL, *q = NULL, *p = NULL;
head = (listnode*)malloc(sizeof(listnode));
head->data = 1;
head->next = NULL;