环形链表实现约瑟夫出圈问题
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 }
运行环境:ubantu
经验总结:写环形链表的时候出了两个错误
1.链表独节点的处理问题,在链表实现的各个环节,一定要注意只有链表头结点的时候是否需要单独处理,否则易引发段错误。例如,只有一个节点了,还在那头也不回的
head = head->m_next,就会出错。
2.约瑟夫出圈每次报完数排除一个人后接着从0开始数,所以要记得重置某些变量的值
注:对于该问题,该实现方法较为复杂,但是健壮性较好,代表了一类问题的处理方法,该模板类具有一定的复用性。
浙公网安备 33010602011771号