约瑟夫环

来源:互联网 发布:js 时间比大小 编辑:程序博客网 时间:2024/04/26 17:27

问题描述:

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

基本要求:

利用单项循环链表存储结构模拟此过程,按照出列的顺序印出各人的编号。

测试数据:

m的初始值为20;n=7,7个人的密码依次为:3,1,7,2,4,8,4,首先m值为6(正确的出列顺序为:6,1,4,7,2,3,5)。

代码:

// Child.h
struct Child {
  int id;   // 编号
  int passwd; // 密码
};
// Node.h
#include "Child.h"
struct Node {
  Child* child;
  Node* next;
};
// CircleLinkList.h
#include "Node.h"
class CircleLinkList {
public:
  CircleLinkList();
  void append(Child* child);
  Child* remove(int index);
  bool isEmpty();
  ~CircleLinkList();
private:
  Node* rear; // 尾指针
  int length;
};
// CircleLinkList.cpp
#include "CircleLinkList.h"
CircleLinkList::CircleLinkList() {
  rear = 0;
  length = 0;
}
void CircleLinkList::append(Child *child) {
  Node* n = new Node;
  n->child = child;
  if (!rear) n->next = n;
  else {
   n->next = rear->next;
   rear->next = n;
  }
  rear = n;
  ++length;
}
Child* CircleLinkList::remove(int index) {
  Node* p = rear;
  Node* f = 0;
  for (int i = -1; i < index % length - 1; ++i)
   p = p->next;
  if (p->next == p) {
   f = p;
   rear = 0;
  }
  else {
   f = p->next;
   p->next = p->next->next;
   if (p != rear)
    rear = p;
  }
  Child* child = f->child;
  delete f;
  --length;
  return child;
}
bool CircleLinkList::isEmpty() {
  return rear == 0;
}
CircleLinkList::~CircleLinkList() {}
// main.cpp
#include "CircleLinkList.h"
#include <iostream>
int main() {
  using namespace std;
  CircleLinkList l;
  cout << "Please input the password of each child by order:" << endl;
  int id = 1;
  int passwd;
  while (cin >> passwd) {
   Child* c = new Child();
   c->id = id;
   c->passwd = passwd;
   l.append(c);
   ++id;
  }
  int m = 20;
  while (!l.isEmpty()) {
   Child* c = l.remove(m - 1);
   id = c->id;
   m = c->passwd;
   delete c;
   cout << id;
   if (!l.isEmpty()) cout << ", ";
  }
  cout << endl;
  return 0;
}
原创粉丝点击