经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C++ » 查看文章
【数据结构】1-2 约瑟夫环问题
来源:cnblogs  作者:巴塞罗那的余晖  时间:2018/11/19 9:24:41  对本文有异议

这里放出两种不同的代码,一个是老师给的(较为复杂),还有一个是自己写的。

自己写的:

  1. #include<iostream>
  2. using namespace std;
  3. struct Node {
  4. int data; //数据单元
  5. Node *link; //指向下一个结点
  6. };
  7. class Josephus
  8. {
  9. private:
  10. Node *head, *current; //head是头结点,current指向当前结点
  11. int sum;//存储链表中元素的个数
  12. public:
  13. Josephus(); //无参构造函数,全部初始化为空
  14. Josephus(int Snumber, int strnumber);//有参构造函数,Snumber为总数,strnumber为开始序号
  15. ~Josephus();//析构函数
  16. void del(Node *&p);
  17. void select(int num);//num为间隔数
  18. void print();
  19. };
  20. Josephus::Josephus()
  21. {
  22. current = NULL;
  23. head = NULL;
  24. sum = 0;
  25. }
  26. Josephus::Josephus(int Snumber, int strnumber)
  27. {
  28. sum = Snumber;
  29. head = new Node;
  30. head->data = strnumber;
  31. current = head;
  32. int dt = strnumber + 1;
  33. for (int i = 1; i < Snumber; i++)
  34. {
  35. Node *p;
  36. p = new Node;
  37. p->data = dt;
  38. current->link = p;
  39. current = p;
  40. dt++;
  41. }
  42. current->link = head;
  43. }
  44. void Josephus::del(Node *&p)
  45. {
  46. Node *d = p->link;
  47. p->link = p->link->link;
  48. delete d;
  49. }
  50. void Josephus::select(int num)
  51. {
  52. int sont = 1;
  53. Node *p = head;
  54. while (sum!= 1)
  55. {
  56. if (sont % (num-1) == 0)
  57. {
  58. del(p);
  59. sum--;
  60. head = p;
  61. }
  62. sont++;
  63. p = p->link;
  64. }
  65. }
  66. void Josephus::print()
  67. {
  68. cout << "剩下的序号有:" << endl;
  69. Node *p = head;
  70. for (int i = 0; i < sum; i++)
  71. {
  72. cout << p->data << " ";
  73. p = p->link;
  74. }
  75. cout << endl;
  76. }
  77. Josephus::~Josephus()
  78. {
  79. /*Node *p = head->link;
  80. while (p!=head)
  81. {
  82. Node *de = p;
  83. p = p->link;
  84. delete de;
  85. }*/
  86. head = NULL;
  87. current = NULL;
  88. }

测试代码:

  1. #include"LinkList.h"
  2. int main()
  3. {
  4. int Snum, stnum,num;
  5. cout << "请输入总数以及开始序号:";
  6. cin >> Snum >> stnum;
  7. Josephus A(Snum, stnum);
  8. A.print();
  9. cout << "请输入间隔数:";
  10. cin >> num;
  11. A.select(num);
  12. A.print();
  13. system("pause");
  14. return 0;
  15. }

其实原理很简单,就是通过循环链表不断循环然后删除就OK

标准代码:

  1. //Circle.h
  2. #include<iostream>
  3. using namespace std;
  4. template<class T>
  5. struct Node //结点结构
  6. {
  7. T data; //结点数据
  8. Node*link;
  9. Node() { link = NULL; }
  10. Node(T e, Node*next = NULL)
  11. {
  12. data = e;
  13. link = next;
  14. }
  15. };
  16. template<class T>
  17. class CircleLinkList
  18. { //不带表头结点的循环链表类
  19. private:
  20. Node<T> *current, *front; //current指向某结点,front指向current前驱
  21. public:
  22. CircleLinkList() :current(NULL), front(NULL) {} //构建空循环链表
  23. CircleLinkList(T *d, int mSize); //利用d数组元素构建循环链表
  24. ~CircleLinkList(); //析构函数
  25. bool InsertAfter(const T&x); //在current所指结点之后插入x
  26. bool RemoveCurrent(T&x); //删除current所指结点
  27. void movenext(int n = 1); //current后移n次
  28. T GetCurrentData() { return current->data; }
  29. bool toLocatioin(T &t);//让current指向t结点,若没有则current不移动
  30. void Output() const; //输出循环链表
  31. };
  32. class Joseph // 约瑟夫环类
  33. {
  34. private:
  35. int numOfBoy; //圈中人数
  36. int startPosition; //报数起始点
  37. int interval; //报数间隔
  38. public:
  39. Joseph(int boys, int start, int m) :
  40. numOfBoy(boys), startPosition(start), interval(m) {}//构造函数
  41. void setNumOfBoy(int num) { numOfBoy = num; }//重置圈中人数
  42. void setStartPosition(int start) { startPosition = start; }//重置起始点
  43. void setInterval(int inter) { interval = inter; }//重置报数间隔
  44. int GetWinner();//求得最终优胜者编号
  45. void print(); //输出约瑟夫环
  46. };
  47. template<class T>
  48. CircleLinkList<T>::CircleLinkList(T *d, int mSize)
  49. { //构造函数,将d数组中的mSize个元素创建循环链表
  50. //采用前插法创建。
  51. int i;
  52. Node<T> *p;
  53. current = new Node<T>;
  54. current->data = d[mSize - 1];
  55. front = current;
  56. for (i = mSize - 2; i >= 0; i--)
  57. {
  58. p = new Node<T>(d[i], current);
  59. current = p;
  60. }
  61. front->link = current;
  62. }
  63. template<class T>
  64. CircleLinkList<T>::~CircleLinkList() //析构函数
  65. {
  66. while (current != front)//销毁循环链表
  67. {
  68. Node<T> *r = current;
  69. current = current->link;
  70. delete r;
  71. }
  72. delete current;
  73. }
  74. template<class T>
  75. bool CircleLinkList<T>::InsertAfter(const T&x)
  76. //在current所指结点之后插入x,current指向x结点
  77. {
  78. Node<T> *s = new Node<T>(x);
  79. if (!s)return false;
  80. if (!current) //原循环链表为空
  81. current = front = s->link = s;
  82. else //原循环链表非空
  83. {
  84. s->link = current->link;
  85. current->link = s;
  86. front = current;
  87. current = s;
  88. }
  89. return true;
  90. }
  91. template<class T>
  92. bool CircleLinkList<T>::RemoveCurrent(T&x) //删除current所指结点
  93. {
  94. if (!current)//循环链表为空
  95. return false;
  96. x = current->data;
  97. if (current == front)//链表中只有一个元素
  98. {
  99. delete current;
  100. current = front = NULL;
  101. }
  102. else
  103. {
  104. front->link = current->link;//修改链表指针
  105. delete current;
  106. current = front->link;
  107. }
  108. return true;
  109. }
  110. template<class T>
  111. void CircleLinkList<T>::Output() const //输出循环链表
  112. {
  113. if (!current)//循环链表为空
  114. return;
  115. Node<T> *p = current;
  116. do
  117. {
  118. cout << p->data << " ";
  119. p = p->link;
  120. } while (p != current);
  121. cout << endl;
  122. }
  123. template<class T>
  124. void CircleLinkList<T>::movenext(int k) //current后移k次
  125. {
  126. for (int i = 1; i <= k; i++)
  127. {
  128. front = current; // front后移
  129. current = current->link; //current后移
  130. }
  131. }
  132. template<class T>
  133. bool CircleLinkList<T>::toLocatioin(T &t)
  134. //将current指向元素为t的结点,若没有则current不移动
  135. {
  136. if (!current)//循环链表为空
  137. return false;
  138. Node<T> *current1 = current, *front1 = front;
  139. while (current1->data != t) //寻找元素t
  140. {
  141. front1 = current1;
  142. current1 = current1->link;
  143. if (current1 == current)// 已寻找一圈没有元素为t的结点
  144. return false;
  145. }
  146. current = current1; //current指向元素为t的结点
  147. front = front1;
  148. return true;
  149. }
  150. int Joseph::GetWinner()//获得最终优胜者
  151. {
  152. CircleLinkList<int> boys;
  153. for (int i = 0; i < numOfBoy; i++)//创建循环链表,编号依次为1~numOfBoy
  154. {
  155. int temp = i + 1;
  156. boys.InsertAfter(temp);
  157. }
  158. boys.toLocatioin(startPosition); //找到报数起点
  159. cout << endl << "依次出列的小孩是:" << endl;
  160. for (int i = 1; i < numOfBoy; i++) //numOfBoy-1个小孩出圈
  161. {
  162. int x;
  163. boys.movenext(interval - 1); //报数
  164. boys.RemoveCurrent(x); //出圈
  165. cout << x << " "; //输出出圈编号
  166. }
  167. return boys.GetCurrentData(); //返回优胜者编号
  168. }
  169. void Joseph::print() //输出约瑟夫环
  170. {
  171. cout << "圈中人数:" << numOfBoy << endl;
  172. cout << "报数起始点:" << startPosition << endl;
  173. cout << "报数间隔:" << interval << endl;
  174. }

测试代码

  1. //测试代码.cpp
  2. #include"Circle.h"
  3. int main()
  4. {
  5. int total, interv, startboy;
  6. cout << "请分别输入人数,起始号码和间隔数"<<endl;
  7. cin >> total >> startboy >> interv;
  8. Joseph jose(total, startboy, interv);
  9. jose.print();
  10. cout << "优胜者编号为: " << jose.GetWinner() << endl;
  11. system("pause");
  12. return 0;
  13. }

 

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号