数据结构(Data structure):用循环链表解决约瑟夫问题(C语言)

0.简介(在以下环境下运行通过):

      运行环境:Linux(ubuntu12.10);

  编译器:gcc;

  语言:C语言;

  作者:Catcher24。

1.问题描述:

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

  约瑟夫问题:(Josephus problem)

  据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。

2.数据结构描述与设计:

  循环链表(空表为只有一个空节点的表,其link指针指向自身)很容易模拟一个环,其数据域可以用来储存编号,加上链表的删除操作,可以很简单的解决约瑟夫问题。

  循环链表的实现以及约瑟夫问题的解决代码如下:

  CircLinkedList.h:该头文件定义了一些需要实现的循环链表的基本函数以及Josephus函数:

 1 /*Author:catcher  qyjiang24@gmail.com
 2  *           -------------------
 3  *           |  node    | link |----
 4  *           ------------------    |
 5  *                ^                |
 6  *                |________________|
 7  */
 8 #include <stdio.h>
 9 #include <stdlib.h>
10 
11 #ifndef _List_H
12 typedef int type;
13 typedef int bool;
14 typedef struct node{
15     type data;
16     struct node* link;
17 }node;
18 typedef struct node* p_node;
19 
20 #define false 0
21 #define true 1
22 
23 p_node init(p_node l);    //初始化函数
24 p_node get_head(p_node l);
25 void make_empty(p_node l);  //将链表置空的函数
26 bool is_empty(p_node l);    //判断链表是否为空
27 p_node find(type x,p_node l);   //查找函数
28 p_node find_pre(type x,p_node l);   //查找前驱节点
29 bool insert_node(type x,p_node l);  //Insert a node
30 bool delete_node(type x,p_node l);  //Delete a node
31 void delete_list(p_node l); //Delete list
32 void print_list(p_node l);  //Print list
33 
34 void Josephus(p_node l,int n,int m);    //Handle Josephus question
35 #endif

  上面的头文件给出各个函数的定义,下面给出函数实现:CircLinkedList.c文件:

  1 #include "CircLinkedList.h"
  2 
  3 p_node init(p_node l)
  4 {
  5     l = malloc(sizeof(node));
  6     l->link = l;
  7 }
  8 
  9 p_node get_head(p_node l)
 10 {
 11     return l;
 12 }
 13 void make_empty(p_node l)
 14 {
 15     p_node first = get_head(l);
 16     if(first->link == first){//It's empty list now;
 17         return;
 18     }
 19     p_node ptr = first->link;
 20     while(ptr != first){
 21         p_node p = ptr;
 22         ptr = ptr->link;
 23         free(p);
 24     }
 25     first->link = first;
 26     return;
 27 }
 28 
 29 bool is_empty(p_node l)
 30 {
 31     return (l->link == l)? true:false;
 32 }
 33 
 34 p_node find(type x,p_node l)
 35 {
 36     p_node ptr = find_pre(x,l);
 37     if(ptr != NULL)
 38         ptr = ptr->link;
 39     return ptr;
 40 }
 41 
 42 p_node find_pre(type x,p_node l)
 43 {
 44     p_node first = get_head(l);
 45     if(l->link == first)
 46         return NULL;
 47     p_node ptr = first->link;
 48     p_node p = NULL;
 49     while(ptr->link != NULL){
 50         p = ptr;
 51         ptr = ptr->link;
 52         if(ptr->data == x)
 53             return p;
 54     }
 55     return NULL;
 56 }
 57 
 58 bool insert_node(type x,p_node l)
 59 {
 60     p_node first = get_head(l);
 61     if(is_empty(l)){
 62         p_node p = malloc(sizeof(node));
 63         p->link = first;
 64         p->data = x;
 65         first->link = p;
 66         return true;
 67     }
 68     p_node ptr = first->link;
 69     while(ptr->link != first){
 70         ptr = ptr->link;
 71     }
 72     p_node p = malloc(sizeof(node));
 73     p->link = first;
 74     p->data = x;
 75     ptr->link = p;
 76     return true;
 77 }
 78 
 79 bool delete_node(type x,p_node l)
 80 {
 81     p_node pptr = find_pre(x,l);
 82     p_node ptr = pptr->link;
 83     pptr->link = ptr->link;
 84     free(ptr);
 85     return true;
 86 }
 87 
 88 void delete_list(p_node l)
 89 {
 90     p_node first = get_head(l);
 91     p_node ptr = first->link;
 92     while(ptr != first){
 93         p_node p = ptr;
 94         ptr = ptr->link;
 95         free(p);
 96     }
 97     free(first);
 98 }
 99 
100 void print_list(p_node l)
101 {
102     p_node first = get_head(l);
103     p_node ptr = first->link;
104     while(ptr != first){
105         printf("%d\t",ptr->data);
106         ptr = ptr->link;
107     }
108     printf("\n");
109 }
110 
111 void Josephus(p_node l,int n,int m)
112 {
113     //Initialization
114     int i,j;
115     for(i = 0;i < n;i++){
116         insert_node(i+1,l);
117     }
118     p_node ptr = l->link;
119     p_node pre = NULL;
120     for(i = 0;i < n-1;i++){
121         for(j = 0;j < m-1;j++){
122             pre = ptr;
123             ptr = ptr->link;
124             if(ptr == get_head(l)){
125                 ptr = ptr->link;
126             }
127         }
128            printf("Number %d is dead\n",ptr->data);
129         delete_node(ptr->data,ptr);
130         ptr = ptr->link;
131     }
132     ptr = l->link;
133     printf("The winner is: %d\n",ptr->data);
134 }

 

  下面给出测试文件main.c:

 1 #include "CircLinkedList.h"
 2 
 3 int main()
 4 {
 5     int m;
 6     int n;
 7     printf("Enter n:\n");
 8     scanf("%d",&n);
 9     printf("Enter m:\n");
10     scanf("%d",&m);
11     p_node p = NULL;
12     p = init(p);
13     Josephus(p,n,m);
14     return 0;
15 }

 

3.问题的解答:

  测试与运行:

  将三个文件放在一个目录下并使用命令:

gcc main.c CircLinkedList.h CircLinkedList.c -o main

  编译,然后使用如下命令运行:

./main

  结果如下图:

《数据结构(Data structure):用循环链表解决约瑟夫问题(C语言)》  

  当然,也可以选择使用makefile来处理。

    原文作者:约瑟夫环问题
    原文地址: https://www.cnblogs.com/catcher24/archive/2013/04/24/3039381.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞