循环单链表,解决约瑟夫问题

约瑟夫问题:

编号为1~N的N个人按顺时针方向围坐一圈,每人持有一个密码(正整数),开始任选一个正整数作为报数上限值M,从第1个人按顺时针方向自1开始顺序报数,报到M时停止报数。报M的人出列,将他的密码作为新的M值,从他顺时针方向上的下一个人开始从1报数,如此下去,直至所有人全部出列为止。

解析:

显然当有人退出圆圈后,报数的工作要从下一个人开始继续,而剩下的人仍然围成一个圆圈,因此可以使用循环单链表。退出圆圈的工作对应着表中节点的删除操作,对于这种删除操作频繁的情况,选用效率较高的链表结构,为了程序指针每次都指向一个具体的代表一个人的节点而不需要判断,链表不带头节点。因此,对于所有人围成的圆圈所对应的数据结构采用一个不带头节点的循环链表来描述。

 1 #include "stdafx.h"
 2 #include <iostream>
 3 #include "string.h"
 4 using namespace std;
 5
 6 typedef struct node
 7 {
 8     int data;
 9     node *next;
10 }node;
11
12 node *create(int n)    //创建节点数量为n的单向循环链表
13 {
14     node *pRet = NULL;
15     if(n != 0)
16     {
17         int n_idx = 1;
18         node *p_node = NULL;
19         p_node = new node[n];
20         if(p_node == NULL)
21             return NULL;
22         else
23             memset(p_node,0,n*sizeof(node));    //初始化内存
24         pRet = p_node;
25         while(n_idx < n)    //构造每一个节点,分别赋值1~n-1
26         {
27             p_node->data = n_idx;
28             p_node->next = p_node+1;
29             p_node = p_node->next;
30             n_idx++;
31         }
32         p_node->data = n;    //构造最后一个节点
33         p_node->next = pRet;//最后一个节点的next指针指向第一个节点
34     }
35     return pRet;
36 }
37
38 int main(int argc,char *argv[])
39 {
40     node *pList = NULL;
41     node *pIter = NULL;
42     int n = 20;
43     int m = 6;
44     pList = create(n);    //构造节点数为20的循环单链表
45     //取数
46     pIter = pList;
47     m %= n;
48     while(pIter != pIter->next)
49     {
50         int i;
51         for(i=1;i<m-1;i++)    //先取到第m-1个节点
52             pIter = pIter->next;
53         cout<<pIter->next->data<<"--";    //输出第m个节点的值
54         pIter->next = pIter->next->next;//删除第m个节点
55         pIter = pIter->next;
56     }
57     cout<<pIter->data<<endl;
58     delete []pList;        //释放申请的空间
59     system("pause");
60     return 0;
61 }

执行结果:

时间: 2024-11-03 21:21:42

循环单链表,解决约瑟夫问题的相关文章

使用java的循环单向链表解决约瑟夫问题

什么是约瑟夫问题 据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止.然而Josephus 和他的朋友并不想遵从.首先从一个人开始,越过k-2个人(因为第一个人已经被越过),并杀掉第k个人.接着,再越过k-1个人,并杀掉第k个人.这

02循环单链表

循环单链表定义:将单链表中终端结点的指针端由空指针改为指向头结点,就使整个单链表形成了 一个环,这种头尾相接的单链表成为单循环链表. 循环链表的数据结构: 1 /* c2-2.h 线性表的单链表存储结构 */ 2 struct LNode 3 { 4 ElemType data; 5 struct LNode *next; 6 }; 7 typedef struct LNode *LinkList; /* 另一种定义LinkList的方法 */ 代码实现: 1 2 3 /* bo2-4.c 设立

循环单链表

//函数声明部分:#include"CirLinkList.h" #define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<stdlib.h> typedef int ElemType; typedef struct linknode { ElemType data; struct linknode *next; }node; void judgement_NULL(node * p); node 

c语言循环单链表

/************************************************************************* > File Name: singleLineTable.c > Author: zshh0604 > Mail: [email protected] > Created Time: 2014年10月15日 星期三 11时34分08秒 **************************************************

_DataStructure_C_Impl:循环单链表

//CycList:循环单链表 #include<stdio.h> #include<stdlib.h> typedef int DataType; typedef struct Node{ DataType data; struct Node *next; }ListNode,*LinkList; //创建一个不带头结点的循环单链表 LinkList CreateCycList(int n){ DataType e; LinkList head=NULL; ListNode *p

用循环单链表实现约瑟夫环

题目:n个人编号分别是1,2,3,...,n,围坐在一张圆桌周围,从编号为k的人开始报数,数到m的人出列.然后他的下一个人开始报数,数到m的那个人又出列:依次循环,直到所有人出列. struct LNode{ int data; LNode *next; }; //n为总人数,k为第一个开始报数的人,m为出列者喊到的数 void solve(int k,int m, int n) { if(k>n || n<=0 || m<=0) { throw "Invalid argume

【C语言数据结构】循环单链表

CircleLinkList.h #ifndef CIRCLE_LINK_LIST #define CIRCLE_LINK_LIST //链表节点 typedef struct _CircleLinkListNode {     struct _CircleLinkListNode *next; }CircleLinkListNode; //循环单链表 typedef void CircleLinkList; /*  * 创建循环单链表  * @return 返回循环单链表的指针  */ Cir

【线性表5】线性表的链式实现:循环单链表

简介 循环单链表 是在在单链表的基础上,用最后的一个结点的指针域指向头结点形成的.因此它在逻辑上是一个环形结构. 循环单链表在实际编程中很少用. 要点:1.遍历结束的标志是 p == [头结点地址],而不是p==NULL 2.表为空的判断标志是:   if( head->next == head   ) 3.在单循环链表中,从任一结点出发都可访问到表中所有结点 循环链表一般还使用尾指针rear保存最后一个结点的地址,因为使用尾指针既可以快速找到 最后一个结点,也可以快速找到头结点. 简单的代码实

【c++版数据结构】之循环单链表的实现(带头结点以及尾节点)

所实现的循环单链表的结构如下图所示: 循环单链表的实现,和上一篇文章单链表的实现大致相同点击打开链接,略有区别: 1:循环判断的条件不再是s == NULL或者s->next == NULL,而是他们是否等于头指针.2: 断开链表时的处理,尾节点的next不是NULL,而是指向头结点 具体细节参考上一篇文章 头文件:SCList.h #ifndef SCLIST_H #define SCLIST_H #include<iostream> #include<cassert> u