Josephus问题解决方法三(单向循环链表标识法)

来源:互联网 发布:c 语言写入txt文件 编辑:程序博客网 时间:2024/06/01 23:09
前面解决Josephus问题时(点击打开链接,点击打开链接),都是找到该同学后,把该同学从环中除去,然后剩下的同学再组成一个新的环,终止条件是p != p->next。下面我们换种方式考虑该问题,可不可以找到该同学后,标识该同学,然后一直循环该环,直到把所有的人都标识,终止循环的条件是已标识人数等于总人数(flag=length),最后"标识"的同学就是获胜者。我把这种方法叫做“单向循环链表标识法”,下面给出代码:

点击(此处)折叠或打开

  1. #include<iostream>
  2. using namespace std;
  3. typedef struct Note{
  4.     char ch;
  5.     struct Note *next;
  6. }*node;

  7. int length;
  8. int flag;

  9. void initNote(node first) {
  10.     first = new Note;
  11.     first->next = NULL;
  12. }

  13. void createNote(node first) {
  14.     node p, q;
  15.     p = first;
  16.     cout << "请依次输入学生的编号:" << endl;
  17.     for (char ch; cin >> ch, ch !='#';) {
  18.         q = new Note;
  19.         p->next = q;
  20.         q->ch = ch;
  21.         cout << q->ch << " ";
  22.         p = q;
  23.         length++;
  24.     }
  25.      p->next=first->next;
  26. }
  27. void searchNote(node first,int n) {
  28.   
  29.     cout << "出队的顺序依次是:" << endl;
  30.     while (true) {                   //死循环,为了找出所有标识结点
  31.         for (int i = 1; i <=n; i++) {
  32.                 
  33.                 first = first->next;
  34.                 if (first->ch == NULL){ //只要循环到ch为空的结点,i减1,并且继续执行for循环
  35.                     i--;
  36.                     continue;
  37.                 }
  38.         }
  39.             flag++;    //只要结点的first->ch=NULL,则标识就增加1
  40.             cout << first->ch << " ";
  41.             if (flag == length) {  //已经找到了所有的标识结点,退出死循环
  42.                 break;
  43.             }
  44.             first->ch = NULL;//把标识结点的数据域置为空
  45.     }
  46.     cout << endl;
  47.     cout << "获胜的同学是:" << endl;
  48.     cout << first->ch;    //打印出获胜者
  49. } 
  50. void deleteNote(node q) {
  51.     node p = q;
  52.     for (; p != q; p = p->next) {
  53.         node no = p;
  54.         delete no;
  55.     }
  56.     cout << "环已销毁!!!" << endl;
  57. }
  58. int main() {
  59.     Note note; 
  60.     initNote(&note);
  61.     createNote(&note);
  62.     cout << endl;
  63.     searchNote(&note,4);
  64.     cout << endl;
  65.     deleteNote(&note);
  66. }
运行结果:

形成环这里不必多说,关键在于void searchNote(node first,int n),思路就是找到同学后,把该同学贴上标签,然后继续循环该环,当找到已经被贴上标签的同学,就跳过该同学,当找到所有的同学后,那么剩下的同学就是获胜 者,当然别忘了,游戏结束后,不能让同学还是手拉手围成一个环,那就是void deleteNote(node q)的功能啦,把该环"销毁"了。上面的解题思路,我想很多朋友会想到,可不可以用数组解决该问题,当然可以啦!关键是清晰的画出程序流程图解,程序写起来会变的相对容易些。
0 0
原创粉丝点击