这里放出两种不同的代码,一个是老师给的(较为复杂),还有一个是自己写的。
自己写的:
- #include<iostream>
- using namespace std;
- struct Node {
- int data; //数据单元
- Node *link; //指向下一个结点
- };
- class Josephus
- {
- private:
- Node *head, *current; //head是头结点,current指向当前结点
- int sum;//存储链表中元素的个数
- public:
- Josephus(); //无参构造函数,全部初始化为空
- Josephus(int Snumber, int strnumber);//有参构造函数,Snumber为总数,strnumber为开始序号
- ~Josephus();//析构函数
- void del(Node *&p);
- void select(int num);//num为间隔数
- void print();
- };
- Josephus::Josephus()
- {
- current = NULL;
- head = NULL;
- sum = 0;
- }
- Josephus::Josephus(int Snumber, int strnumber)
- {
- sum = Snumber;
- head = new Node;
- head->data = strnumber;
- current = head;
- int dt = strnumber + 1;
- for (int i = 1; i < Snumber; i++)
- {
- Node *p;
- p = new Node;
- p->data = dt;
- current->link = p;
- current = p;
- dt++;
- }
- current->link = head;
- }
- void Josephus::del(Node *&p)
- {
- Node *d = p->link;
- p->link = p->link->link;
- delete d;
- }
- void Josephus::select(int num)
- {
- int sont = 1;
- Node *p = head;
- while (sum!= 1)
- {
- if (sont % (num-1) == 0)
- {
- del(p);
- sum--;
- head = p;
- }
- sont++;
- p = p->link;
- }
-
-
- }
- void Josephus::print()
- {
- cout << "剩下的序号有:" << endl;
- Node *p = head;
- for (int i = 0; i < sum; i++)
- {
- cout << p->data << " ";
- p = p->link;
- }
- cout << endl;
- }
- Josephus::~Josephus()
- {
- /*Node *p = head->link;
- while (p!=head)
- {
- Node *de = p;
- p = p->link;
- delete de;
- }*/
- head = NULL;
- current = NULL;
- }
测试代码:
- #include"LinkList.h"
- int main()
- {
- int Snum, stnum,num;
- cout << "请输入总数以及开始序号:";
- cin >> Snum >> stnum;
- Josephus A(Snum, stnum);
- A.print();
- cout << "请输入间隔数:";
- cin >> num;
- A.select(num);
- A.print();
- system("pause");
- return 0;
- }
其实原理很简单,就是通过循环链表不断循环然后删除就OK
标准代码:
- //Circle.h
- #include<iostream>
- using namespace std;
- template<class T>
- struct Node //结点结构
- {
- T data; //结点数据
- Node*link;
- Node() { link = NULL; }
- Node(T e, Node*next = NULL)
- {
- data = e;
- link = next;
- }
- };
- template<class T>
- class CircleLinkList
- { //不带表头结点的循环链表类
- private:
- Node<T> *current, *front; //current指向某结点,front指向current前驱
- public:
- CircleLinkList() :current(NULL), front(NULL) {} //构建空循环链表
- CircleLinkList(T *d, int mSize); //利用d数组元素构建循环链表
- ~CircleLinkList(); //析构函数
- bool InsertAfter(const T&x); //在current所指结点之后插入x
- bool RemoveCurrent(T&x); //删除current所指结点
- void movenext(int n = 1); //current后移n次
- T GetCurrentData() { return current->data; }
- bool toLocatioin(T &t);//让current指向t结点,若没有则current不移动
- void Output() const; //输出循环链表
- };
- class Joseph // 约瑟夫环类
- {
- private:
- int numOfBoy; //圈中人数
- int startPosition; //报数起始点
- int interval; //报数间隔
- public:
- Joseph(int boys, int start, int m) :
- numOfBoy(boys), startPosition(start), interval(m) {}//构造函数
- void setNumOfBoy(int num) { numOfBoy = num; }//重置圈中人数
- void setStartPosition(int start) { startPosition = start; }//重置起始点
- void setInterval(int inter) { interval = inter; }//重置报数间隔
- int GetWinner();//求得最终优胜者编号
- void print(); //输出约瑟夫环
- };
- template<class T>
- CircleLinkList<T>::CircleLinkList(T *d, int mSize)
- { //构造函数,将d数组中的mSize个元素创建循环链表
- //采用前插法创建。
- int i;
- Node<T> *p;
- current = new Node<T>;
- current->data = d[mSize - 1];
- front = current;
- for (i = mSize - 2; i >= 0; i--)
- {
- p = new Node<T>(d[i], current);
- current = p;
- }
- front->link = current;
- }
- template<class T>
- CircleLinkList<T>::~CircleLinkList() //析构函数
- {
- while (current != front)//销毁循环链表
- {
- Node<T> *r = current;
- current = current->link;
- delete r;
- }
- delete current;
- }
- template<class T>
- bool CircleLinkList<T>::InsertAfter(const T&x)
- //在current所指结点之后插入x,current指向x结点
- {
- Node<T> *s = new Node<T>(x);
- if (!s)return false;
- if (!current) //原循环链表为空
- current = front = s->link = s;
- else //原循环链表非空
- {
- s->link = current->link;
- current->link = s;
- front = current;
- current = s;
- }
- return true;
- }
- template<class T>
- bool CircleLinkList<T>::RemoveCurrent(T&x) //删除current所指结点
- {
- if (!current)//循环链表为空
- return false;
- x = current->data;
- if (current == front)//链表中只有一个元素
- {
- delete current;
- current = front = NULL;
- }
- else
- {
- front->link = current->link;//修改链表指针
- delete current;
- current = front->link;
- }
- return true;
- }
- template<class T>
- void CircleLinkList<T>::Output() const //输出循环链表
- {
- if (!current)//循环链表为空
- return;
- Node<T> *p = current;
- do
- {
- cout << p->data << " ";
- p = p->link;
- } while (p != current);
- cout << endl;
- }
- template<class T>
- void CircleLinkList<T>::movenext(int k) //current后移k次
- {
- for (int i = 1; i <= k; i++)
- {
- front = current; // front后移
- current = current->link; //current后移
- }
- }
- template<class T>
- bool CircleLinkList<T>::toLocatioin(T &t)
- //将current指向元素为t的结点,若没有则current不移动
- {
- if (!current)//循环链表为空
- return false;
- Node<T> *current1 = current, *front1 = front;
- while (current1->data != t) //寻找元素t
- {
- front1 = current1;
- current1 = current1->link;
- if (current1 == current)// 已寻找一圈没有元素为t的结点
- return false;
- }
- current = current1; //current指向元素为t的结点
- front = front1;
- return true;
- }
- int Joseph::GetWinner()//获得最终优胜者
- {
- CircleLinkList<int> boys;
- for (int i = 0; i < numOfBoy; i++)//创建循环链表,编号依次为1~numOfBoy
- {
- int temp = i + 1;
- boys.InsertAfter(temp);
- }
- boys.toLocatioin(startPosition); //找到报数起点
- cout << endl << "依次出列的小孩是:" << endl;
- for (int i = 1; i < numOfBoy; i++) //numOfBoy-1个小孩出圈
- {
- int x;
- boys.movenext(interval - 1); //报数
- boys.RemoveCurrent(x); //出圈
- cout << x << " "; //输出出圈编号
- }
- return boys.GetCurrentData(); //返回优胜者编号
- }
- void Joseph::print() //输出约瑟夫环
- {
- cout << "圈中人数:" << numOfBoy << endl;
- cout << "报数起始点:" << startPosition << endl;
- cout << "报数间隔:" << interval << endl;
- }
测试代码
- //测试代码.cpp
- #include"Circle.h"
- int main()
- {
- int total, interv, startboy;
- cout << "请分别输入人数,起始号码和间隔数"<<endl;
- cin >> total >> startboy >> interv;
- Joseph jose(total, startboy, interv);
- jose.print();
- cout << "优胜者编号为: " << jose.GetWinner() << endl;
- system("pause");
- return 0;
- }