C++实现约瑟夫环的循环单链表

约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知 n 个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。. 从编号为 k 的人开始报数,数到 m 的那个人出圈;他的下一个人又从 1 开始报数,数到 m 的那个人又出圈;依此规律重复下去,直到剩余最后一个胜利者。. 例如:有10个人围成一圈进行此游戏,每个人编号为 1-10 。. 若规定数到 3 的人出圈。. 则游戏过程如下。. (1)开始报数,第一个数到 3 的人为 3 号,3 号出圈。. 1, 2, 【 3 】, 4, 5, 6, 7, 8, 9, 10。. (2)从4号重新从1开始计数,则接下来数到3的人为6号,6号出圈。

废话不多说,直接上代码:

下面是头文件,命名为”约瑟夫环.h“

#ifndef Josephus_circle//判断是否被定义过Josephus_circle
#define Josephus_circle

struct Node//定义一个结构体,用来表示每一个结点
{
 int data;//表示每一个结点的数字,也就是序号
    Node* next;//定义一个结构体指针,用来指向后一个结点
};

class Josephus//定义一个类,里面包含有三个接口,和两个私有成员变量
{
public :
 Josephus(int n);//定义一个构造函数,用来创建一个约瑟夫环
 ~Josephus();//析构函数,用以销毁一个约瑟夫环
 void ResultShow(int m);//展示出圈顺序
private :
 Node * rear,*first;//定义一个节点形指针,用来指向最后一个结点
};
#endif

下面是接口的具体实现,命名为“约瑟夫环.cpp”

#include<iostream>//引入输入输出流
#include"约瑟夫环.h"//引入约瑟夫环头文件

using namespace std;

 Josephus::Josephus(int n)
{
  first=rear = new Node;//将头指针和尾指针指向第一个新建的结点,也就是初始化指针
  rear->data = 1;//首先,将第一个结点数据域赋值为1
  for (int i = 2; i <= n; i++) //从2开始
  {
   Node* s = new Node;//定义一个Node形指针s,指向新建的一个结点
   rear->next = s;//将指向头结点的尾指针指向下一个结点,也就是s所指的结点
   s->data = i;//将新建的结点数字域赋值为i
   rear = s;//将尾结点移动到新建结点s
  }
  rear->next = first;//在循环过后,将尾结点和头节点连接起来,构成循环链表
}
Josephus::~Josephus()
{
 if (first!=rear)//判断环是否为空
 {
  while (first != rear)//每次循环都是当头节点不等于尾结点时候,开始删除:……
  {
   Node * p = first;//定义一个新的节点形指针,指向头节点,用作暂存要删去的结点
   first = first->next;//将头节点移动到下一个结点
   delete p;//删除之前头节点所指向的结点
  }
  delete rear;//在删除完成后,剩下的最后就只有尾结点了,删除即可
 }
 else
 {
  cout << "约瑟夫环为空,请先建立新环!" << endl;//空表提示
 }
}
void Josephus::ResultShow(int m)
{
 cout << "出环顺序为:" << endl;
 Node * p = first;//定义一个Node类型的p,等于first
 Node * pre=first,* reserve=nullptr;//定义pre等于first,和一个代替p指针被删除的结点的指针
 int count = 1;//定义一个计数的count使其为一
 while (p->next != p)//如果p->next所指向的结点是p的话,表示,这已经是最后一个结点了,该节点为最后出圈
 {
  if (count < m)//count来计数,每次到了m就出圈对应结点
  {
   pre = p;//将pre等于p,以便于表示p变换前的结点
   p = p->next;//p向下一结点移动
   count++;//移动一次count加一次
  }
  else//每次count=m时候就开始删除对应结点
  {
   pre->next = p->next;//首先从环中摘去要删除的p所指的结点
   reserve = p;//使用reserve来保存被摘去的结点p
   cout << p->data << "\t";//输出结点p所数据域,输出在屏幕上表示p结点的出圈
   p = p->next;//p指向下一结点,以便于下一轮的循环
   delete reserve;//删除保存p的reserve所对应的结点
   count = 1;//将计数恢复为1,以便下一轮计数
  }
 }
 cout << p->data << endl;//这最后一个就是最后出圈的结点,也就是所谓的胜利者,最后单独输出屏幕
 delete p;//输出最后再删除这一结点,释放内存
 pre=first=rear=p = NULL;//避免野指针出现使其指向空
}

下面是main函数,命名为“约瑟夫环_main.cpp”

#include<iostream>//引入输入输出流
#include"约瑟夫环.h"//引入头文件

using namespace std;

//主函数区域
int main() {
 int m, n;
 cout << "请输入约瑟夫环人数以及密码\n";
 cout << "人数n:";
 cin >> n;
 cout << endl << "密码m:";
 cin >> m;
 Josephus L(n);//创建一个约瑟夫环,环数为10
 L.ResultShow(m);//定义密码m,输出出圈顺序
 return 0;
}

下面是运行截图:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 浅析C++中单链表的增、删、改、减

    首先是是一个简单的例子,单链表的建立和输出.程序1.1 复制代码 代码如下: #include<iostream>#include<string>using namespace std;struct Student{ string name; string score; Student *next;//定义了指向Candidate类型变量的指针};int main(){ int n;// cout<<"请输入学生的总数:"; cin>>n

  • C++使用模板实现单链表

    本文实例为大家分享了用模板实现单链表,供大家参考,具体内容如下 话不多说 直接上代码 #include <iostream> using namespace std; template<typename E> class CLink; template<typename T> class Node { friend class CLink<T>; public: /* 构造函数和析构函数一般不加类型参数 本类类中除了构造函数和析构函数以外 其它的地方都要加上

  • C++中单链表的建立与基本操作

    准备数据 准备在链表操作中需要用到的变量及数据结构 示例代码如下: 复制代码 代码如下: struct Data   //数据结点类型 { string key;  //关键字  string name; int age;};struct CLType  //定义链表结构 { Data nodeData; Data *nextNode;}; 定义了链表数据元素的类型Data以及链表的数据结构CLType.结点的具体数据保存在一个结构Data中,而指针nextNode用来指向下一个结点. 我们可以

  • C++实现单链表按k值重新排序的方法

    本文实例讲述了C++实现单链表按k值重新排序的方法.分享给大家供大家参考,具体如下: 题目要求: 给定一链表头节点,节点值类型是整型. 现给一整数k,根据k将链表排序为小于k,等于k,大于k的一个链表. 对某部分内的节点顺序不做要求. 算法思路分析及代码(C) 思路:将链表分为小于k.等于k.大于k的三个链表,然后再合并. 链表结点定义: typedef struct Node { int data; struct Node* next; }node, *pNode; 算法代码: pNode s

  • C++ 单链表的基本操作(详解)

    链表一直是面试的高频题,今天先总结一下单链表的使用,下节再总结双向链表的.本文主要有单链表的创建.插入.删除节点等. 1.概念 单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素. 链表中的数据是以结点来表示的,每个结点的构成:元素 + 指针,元素就是存储数据的存储单元,指针就是连接每个结点的地址数据.如下图: 2.链表的基本操作 SingleList.cpp: #include "stdafx.h" #include "SingleList.h&

  • 利用C++简单实现顺序表和单链表的示例代码

    本文主要给大家介绍了关于C++实现顺序表和单链表的相关内容,分享出来供大家参考学习,话不多说,来一起看看详细的介绍: 一.顺序表示例代码: #include <assert.h> #include <iostream> using namespace std; typedef int Datatype; class SeqList { public: SeqList() :_array(NULL) ,_size(0) ,_capacity(0) { } SeqList(const

  • C++实现单链表的构造

    单链表的构造,包括最常用函数,setData(),Insert(),Remove(),getData(),Search(). 代码如下: #include <iostream> #include <stdlib.h> using namespace std; template<class T> struct LinkNode{ T data; LinkNode<T> *link; LinkNode(LinkNode<T> *ptr=NULL){l

  • C++使用模板实现单链表(类外实现)

    本文实例为大家分享了C++使用模板实现单链表的具体代码,供大家参考,具体内容如下 这一篇可以和上一篇点击打开链接 模板实现单链表进行对比 看类外实现和类内实现的区别 代码: #include <iostream> using namespace std; template<typename T> class CLink { public: class Node; CLink();//无参的构造函数 void InsertHead(T data);//头插 void InsertTa

  • C++实现单链表删除倒数第k个节点的方法

    本文实例讲述了C++实现单链表删除倒数第k个节点的方法.分享给大家供大家参考,具体如下: 题目: 删除单链表中倒数第k个节点 解题思路及算法代码: 标尺法,定义两个指针指向链表头结点,先让一个走k步,然后两个指针同时开始走,当先走的指针走到末尾时,后走的指针指向的结点就是需要删除的结点. 单链表结构定义: typedef struct Node { int data; struct Node* next; }node, *pLinkedList; 删除倒数第K结点操作代码: //head表示头结

  • C++单链表实现大数加法

    本文实例为大家分享了C++单链表实现大数加法,供大家参考,具体内容如下 Input Format 输入文件包括两行. 第一行包括一个正整数,保证位数不超过1000000. 第二行包括一个正整数,保证位数不超过1000000. Output Format 输出文件包括一行. 第一行包括一个正整数. Sample Input 10558 22 Sample Output 10580 #include <iostream> using namespace std; class BigData { f

随机推荐