首页 > 代码库 > 用循环链表解决约瑟夫环问题

用循环链表解决约瑟夫环问题

约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。

下面我们用循环列表模拟这个过程:

 1 //节点定义与单链表相同,在此省略
 2 //use cyclical linked list to solve josephus problem
 3 template <typename Type> class LinkedList {
 4 private:
 5     Node<Type> *head;
 6 public:
 7     LinkedList() {
 8         head = NULL;
 9     }
10 
11     ~LinkedList() {
12         if(head==NULL){
13             return;
14         }
15         //head表示尾节点,head->next表示头节点
16         Node<Type> *current_node = head->next;
17         //拆成单链表
18         head->next=NULL;
19         while (current_node != NULL) {
20             Node<Type> *delete_node = current_node;
21             current_node = current_node->next;
22             delete delete_node;
23         }
24     }
25 
26     bool insert(Node<Type> *node, int index) {
27         if (head == NULL) {
28             if (index != 0) {
29                 return false;
30             }
31             head = node;
32             //只有一个节点时,next指向自己
33             head->next=head;
34             return true;
35         }
36         if (index == 0) {
37             node->next = head->next;
38             head->next = node;
39             return true;
40         }
41         Node<Type> *current_node = head->next;
42         int count = 0;
43         while (current_node != head && count < index - 1) {
44             current_node = current_node->next;
45             count++;
46         }
47         if (count == index - 1) {
48             node->next = current_node->next;
49             current_node->next = node;
50             //如果加到链表末尾,需更新尾节点
51             if(node==head->next){
52                head=node;
53             }
54             return true;
55         }
56         return false;
57     }
58 
59     //删除数到m的元素并按被删顺序输出,最后被输出的即为留到最后的
60     void output_josephus(int m){
61         Node<Type> *current_node=head;
62         //之后不再使用head指针,所以在这里把它指空,防止最后成为野指针,
63         //因为尾节点可能会被删掉
64         head=NULL;
65         //循环条件:剩下不止一个元素
66         while(current_node->next!=current_node){
67             //从尾节点开始数,数到m时恰好是从头数第m-1个元素
68             for(int i=1;i<m;i++){
69                 current_node=current_node->next;
70             }
71             cout<<current_node->next->data<<" ";
72             Node<Type> *delete_node=current_node->next;
73             current_node->next=current_node->next->next;
74             delete delete_node;
75         }
76         //最后剩余的一个节点
77         cout<<current_node->data<<endl;
78         delete current_node;
79     }
80 };

 

用循环链表解决约瑟夫环问题