约瑟夫问题——循环链表C++

来源:互联网 发布:5g网络相关的股票 编辑:程序博客网 时间:2024/05/17 04:06

  • 什么是约瑟夫问题?

约瑟夫问题是一个有名的问题,编号为1-N的N个人安顺时针围坐一圈,选取M为报数的上限,从第一个人按顺时针开始报数,将第M个人出列,,下一个人继续从1开始报数,报到M的人再出列,直至所有的人全部出列为止。

  • 循环链表:

循环链表与单链表一样,是一种链式的存储结构。区别在于循环链表的最后一个节点的指针指向该循环链表的第一个节点或头结点,从而形成一个环。在建立一个循环链表的时候,要注意以下几点:

1、建立循环链表的时候,必须要让其最后一个节点指向链表的第一个节点或头结点,而不像单链表将租后节点的下一个指向NULL;

2、判断循环链表是否到表尾的方法是采用判断该节点的链域值(下一个节点的地址)是否是表头节点的方法,即当链域值等于表头指针时,说明已到链尾,而不像单链表中判断链域值是否为NULL。

  • 用循环链表来解答约瑟夫问题:
当有人出列之后,报数要从下一个继续开始,剩余的人仍然围成一个圈,所以可以使用循环链表。出列的工作对应表中的节点被删除;为了使链表中的每个节点对应一个具体的人的节点,因此链表不带头结点。因此,对于所有人围成的圆圈所对应的数据结构可采用一个不带头结点的循环链表来实现。

为记录退出的人的先后顺序,采用一个顺序表进行存储。程序结束后在输出依次出列的人的编号。

程序代码如下:

//约瑟夫问题#include <iostream>using namespace std;struct Node {int data;Node *next;};//构造节点数量为n的单项循环链表Node *node_create(int n){Node *pRet=NULL;if(n!=0){int n_idx=1;Node *p_node=NULL;//构造n个节点p_node=new Node[n];if(p_node==NULL)return NULL;elsememset(p_node,0,n*sizeof(Node));//初始化内存pRet=p_node;while(n_idx<n)//构造循环链表{//初始化链表的每个节点从1到np_node->data=n_idx;p_node->next=p_node+1;p_node=p_node->next;n_idx++;}p_node->data=n;p_node->next=pRet;}return pRet;}int main(){Node *pList=NULL;Node *pIter=NULL;int n=20;//设置总人数有20人int m=6;//初始报数的上限值pList=node_create(n);//构造节点数量为n的循环链表//约瑟夫循环取数pIter=pList;m%=n;while(pIter!=pIter->next)//该链表不是空表{int i;//取第m-1个节点for(i=1;i<m-1;i++){pIter=pIter->next;}//取第m个绩点的值cout<<pIter->next->data<<" ";//删除第m个节点pIter->next=pIter->next->next;pIter=pIter->next;}cout<<pIter->data<<endl;delete []pList;return 0;}

运行结果如下:

原创粉丝点击