时光飞逝~

环形链表实现约瑟夫出圈问题
  1 /*
  2 * title: Joseph ones
  3 * author: SuperLong
  4 * date:2013.7.17
  5 * version 1.0
  6 * 
  7 */
  8 /*
  9     由N个人围成首尾相连的圈报数,从第1个人开始报,报到M的人出圈,剩余的人组成圈继续从1开始报数,直到所有人出圈为止。
 10 */
 11 #include <iostream>
 12 #include <list>
 13 #include <stdio.h>
 14 //针对于类似于约瑟夫问题的环形模版链表
 15 template <typename T>
 16 class CircleList
 17 {
 18 public:
 19     //构造、析构
 20     CircleList():m_head(NULL),m_tail(NULL),m_pos(0)
 21     {
 22     }
 23     ~CircleList(){
 24         clear();
 25     }
 26     //清空
 27     void clear()
 28     {
 29         while(m_head)
 30         {
 31             Node *node = m_head;
 32             m_head = m_head->m_next;
 33             delete node;
 34         }
 35         m_head = NULL;
 36     }
 37     //尾部压入
 38     void push_back(T data)
 39     {
 40         Node * node = new Node(data,m_head);
 41         if(m_tail)
 42         {
 43              m_tail->m_next = node;
 44              m_tail = m_tail->m_next;
 45         }
 46         else
 47         {
 48             m_head = m_tail = node;
 49         }
 50     }
 51     //判空
 52     bool empty()
 53     {
 54         if(m_head)
 55             return false;
 56         return true;
 57     }
 58     //删除当前头节点,下个节点为头节点
 59     void erase()
 60     {
 61         if(m_tail!=m_head&&m_head->m_next!=m_tail)
 62         {
 63             Node * node = m_head;
 64             m_head = m_head->m_next;
 65             m_tail->m_next=m_head;
 66             delete node;
 67         }
 68         else if(m_tail!=m_head)
 69         {
 70             delete m_head;
 71             m_head = m_tail;
 72         }
 73         else
 74         {
 75             delete m_head;
 76             m_head=NULL;
 77             m_tail=NULL;
 78         }
 79     }
 80     //从头节点移动m_pos步
 81     T& to_pos()
 82     {
 83         while(--m_pos)
 84         {
 85             if(m_tail!=m_head)
 86             {
 87                 m_tail=m_head;
 88                 m_head = m_head->m_next;
 89             }
 90         }
 91         return m_head->m_data;
 92     }
 93     //获取需要移动的步数
 94     void get_pos(int pos)
 95     {
 96         m_pos = pos;
 97     }
 98 private:
 99     //节点
100     class Node
101     {
102     public:
103         Node(T data,Node* next):m_data(data),m_next(next){}
104         Node* m_next;
105         T m_data;
106     };
107 private:
108     Node* m_head;
109     Node* m_tail;
110     int m_pos;//在此程序中代表报数的
111 };
112 int  main()
113 {
114     //控制台界面
115     CircleList <int> c;
116     printf("请输入玩家人数。\n");
117     int N;
118     scanf("%d",&N);
119     printf("请输入报数数目。\n");
120     int M;
121     scanf("%d",&M);
122     //初始化环形队列编号
123     for(int i=0;i<N;i++)
124     {
125         c.push_back(i+1);
126     }
127     c.get_pos(M);
128     int i=1;
129     //出圈
130     while(!c.empty())
131     {
132         int id = c.to_pos();
133         printf("第%d次::%d出列\n",i++,id);
134         c.erase();
135         c.get_pos(M);
136     }
137     printf("\n");
138     return 0;
139 }
View Code

 

运行环境:ubantu

经验总结:写环形链表的时候出了两个错误

1.链表独节点的处理问题,在链表实现的各个环节,一定要注意只有链表头结点的时候是否需要单独处理,否则易引发段错误。例如,只有一个节点了,还在那头也不回的

head = head->m_next,就会出错。

2.约瑟夫出圈每次报完数排除一个人后接着从0开始数,所以要记得重置某些变量的值

注:对于该问题,该实现方法较为复杂,但是健壮性较好,代表了一类问题的处理方法,该模板类具有一定的复用性。

posted on 2013-07-18 22:27  时光飞逝~  阅读(277)  评论(0)    收藏  举报