一、约瑟夫问题
假设n个依次顺序编号1,2,…,n的竞赛者排成一个环形队列。每人均持有一个密码m,从第1个人开始,从1开始循环计数,每数到第m时,则让让其出队列。然后从下一个人开始重新从1开始计数,继续进行下去。这个过程一直进行到所有的人都出队列为止。最后出列者为优胜者。请输出给定条件下出队列的顺序。
二、题目要求
请结合第二章节:线性表相关内容,分析问题性质和操作方法,并完成代码编写。具体请完成如下内容:
1.分析问题,问题实质可以理解为何种数据结构问题(逻辑结构问题)。
2.根据分析,写出问题的ADT定义。
3.确定数据的存储方法,并定义相关数据类型。
4.描述实现的操作算法。
5.写出完整代码,运行调试输出结果。
必要时加上适当的图示。
分析题目得出,该问题用循环链表可解。
ADT Josephus
Data:
每个数据元素类型相同。相邻元素具有前驱与后继关系,且第一个元素与最后一个元素互为前驱或后继。
Operation:
Josephus
前置条件:线性表不存在
输入:无
功能:线性表的初始化
输出:无
后继条件:建立空线性表
m_Init:
前置条件:线性表(空)存在
输入:人数n,密码M
功能:线性表的初始化
输出:无
后继条件:创建一个有N个元素的循环链表
m_Run:
前置条件:线性表存在
输入:无
功能:循环计数,删除特定的元素
输出:无
后继条件:循环链表减少至剩下一个元素
m_Destroy:
前置条件:线性表存在
输入:无
功能:销毁线性表
输出:无
后继条件:释放内存
END ADT
//Josephus.h
#ifndef JOSEPHUS_H_
#define JOSEPHUS_H_
#include <iostream>
#include <iomanip>
using namespace std;
template <typename T>
struct Node
{
T data;
Node<T> *next;
};
template <typename T>
class Josephus
{
private:
int m_length;
Node<T> *head;
int m_n;
int m_m;
public:
Josephus();
void m_Init(); //设置游戏人数和游戏密码M
void m_Run(); //出圈
void m_Destroy(); //释放内存
void m_Game(); //游戏
};
#endif
template <typename T>
Josephus<T>::Josephus()
{
head = new Node<T>;
head->next = NULL;
m_length = 0;
m_n = 0;
m_m = 0;
}
template <typename T>
void Josephus<T>::m_Init()
{
Node<T> *p, *q;
q = head;
if (head->next != NULL)
head->next = NULL;
cout << "请设置参加游戏的人数n(n > 0):";
cin >> m_n;
while (m_n <= 0)
{
cout << "游戏人数设置错误,请重新设置:";
cin >> m_n;
}
for (int i = 0; i < m_n; i++)
{
p = new Node<T>;
p->data = i + 1;
q->next = p;
q = p;
q->next = head->next;
m_length++;
}
cout << "\n人数设置完毕." << endl;
cout << "\n请输入游戏密码M(M > 0):";
cin >> m_m;
while (m_m <= 0)
{
cout << "游戏密码设置错误,请重新设置:";
cin >> m_m;
}
system("pause"); //暂停
system("cls"); //清屏
}
template <typename T>
void Josephus<T>::m_Run()
{
Node<T> *p, *q, *t;
p = head->next;
if (head->next == NULL)
cout << "\n游戏出现异常,请确认是否设置了游戏人数和游戏密码" << endl;
cout << "游戏者淘汰的编号和顺序:" << endl;
while (p->next != NULL && p->next != p)
{
for (int i = 1; i < m_m - 1; i++)
p = p->next;
q = p;
p = p->next;
cout << p->data << '\t';
q->next = q->next->next;
t = p;
p = p->next;
delete t;
m_length--;
}
cout << endl;
cout << "\n游戏的胜利者的编号为" << p->data << endl;
}
template <typename T>
void Josephus<T>::m_Destroy()
{
Node<T> *p, *q;
p = head;
q = p;
for (int i = 0; i < m_length; i++)
{
q = q->next;
delete p;
p = q;
}
m_length = 0;
}
template <typename T>
void Josephus<T>::m_Game()
{
this->m_Init();
this->m_Run();
this->m_Destroy();
}
//Josephus.cpp
#include "Josephus.h"
#include <iostream>
using namespace std;
int main()
{
Josephus<int> jos;
jos.m_Game();
return 0;
}
实验结果: