Josephu 问题为:设编号为1,2,…,n的n个人围坐一圈,约定编号为k(1≤k≤n)的人从1开始报数,数到m 的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,以此类推,直到所有人出列为止,由此产生一个出队编号的序列。
Josephu问题可以用一个不带头结点的循环链表解决。请编写算法,先构成一个有n个结点的不带头结点的循环链表,然后由k结点起从1开始计数,计到m时,对应结点从链表中删除,然后被删除结点的下一个结点又从1开始计数,直到最后一个结点从链表中删除时算法结束。
新定义的不带头结点的循环链表如下:
#include "CList.h"
template
class CListX : public List
{
public:
//构造函数
CListX() { this->header->next = this->header; }
~CListX() //析构函数
{
get_node(this->_size)->next = NULL; //还原成单链表
}
LNode *get_header() { return this->header; }
LNode *get_node(int i)
{
int j = 1;
LNode *p = this->header;
while (p->next != this->header && j < i)
{
p = p->next;
++j;
}
if (!p || j != i) return NULL;
else return p;
}
int locate_elem(T e)
{
LNode *p = this->header;
for (int i = 1; p; p = p->next, i++)
if (p->data == e) return i;
return 0;
}
void insert(T const &e)
{
LNode *p = this->header;
LNode *q;
if (this->empty()) p->data = e;
else
{
q = new LNode();
q->data = e;
get_node(this->_size)->next = q;
q->next = p;
}
this->_size++;
return;
}
T remove(LNode *p)
{
T e = p->data; //备份删除结点数值
LNode *q;
//找到前一个结点的位置
int location = locate_elem(e) - 1;
//处理前一个结点不是最后一个结点
if (location) q = get_node(location);
//处理前一个结点结点是最后一个结点
else q = get_node(this->_size);
//处理删除结点是头结点
if (p == this->header) this->header = p->next;
q->next = p->next;
this->_size--;
delete p; // 删除并释放结点
return e;
}
};
定义文件中的主程序如下:
#include "CListX.h"
#include
using namespace std;
//创建不带头结点的循环链表
void creat_CListX(CListX &L)
{
cout << "请顺序输入链表元素Ctrl+Z结束,"
<< "建立带头结点的链表:\n";
int x;
while (cin >> x) L.insert(x); //按Ctrl+Z组合键结束输入
cin.clear(); // 更改cin的状态标示符
rewind(stdin); //清空输入缓存区
}
//打印不带头结点的循环链表
void print_CListX(CListX &L)
{
if (L.empty())
{
cout << "双向链表为空!\n";
return;
}
LNode *p = L.get_header();
cout << "双向链表共有" << L.size() << "个元素:\n";
while (p->next != L.get_header())
{
cout << p->data << ' ';
p = p->next;
}
cout << p->data << "\n";
cout << endl;
}
//解决参数为k、m的josephu问题
void josephu(int k, int m, CListX &L)
{
LNode *p = L.get_node(k + m);
cout << "josephu问题出队编号的序列为:" << endl;
while (L.size() > 1)
{
cout << p->data << ' ';
L.remove(p);
int i = 1;
while (i <= m)
{
p = p->next;
++i;
}
}
cout << L.get_header()->data;
cout << endl;
}
int main()
{
CListX L;
creat_CListX(L);
print_CListX(L);
josephu(2, 3, L);
return 0;
}