约瑟夫环问题简单练习

背景故事

约瑟夫环问题起源于一个犹太故事。约瑟夫环问题的大意如下:

  罗马人攻占了桥塔帕特,41个人藏在一个山洞中躲过了这场浩劫。这41个人中,包括历史学家Josephus(约瑟夫)和他的一个朋友。剩余的39个人为了表示不向罗马人屈服,决定集体自杀。大家制定了一个自杀方案,所有这41个人围成一个圆圈,由第一个人开始顺时针报数,每报数为3的人就立刻自杀,然后再由下一个人重新开始报数,仍然是每报数为3的人就立刻自杀……,直到所有的人都自杀身亡为止。

  约瑟夫和他的朋友并不想自杀,于是约瑟夫想到了一个计策,他们两个同样参与到自杀方案中,但是最后却躲过了自杀。请问,他们是怎么做到的?

问题描述

约瑟夫环:

  • 一群人沿圆桌坐成一个环(N)
  • 从某个编号开始报数(K)
  • 数到某个数(m)的时候,此人出列,下一个人重新报数
  • 一直循环,知道所有人出列,约瑟夫环结束

解决方案

这是一个典型的循环链表题目。我们需要创建一个循环链表,依照游戏规则,依次进行删除结点操作。直至链表为空,打印出的元素顺序即为出局顺序!


这里写图片描述

下面用C语言写出约瑟夫环问题的程序,创建链表,添加数据,依次删除结点操作,直到链表为空表,源代码如下:

#include <stdio.h>
#include <stdlib.h>

#define LEN sizeof(node)
typedef struct Node {
    int data;
    struct Node *next;
}node;

//创建一个n个结点的链表
node *CreateLink(int n) {
    node *head, *pf, *pb;     //head:头结点    pf:当前位置的结点     pb:新建的结点
    //创建n个结点——循环n次
    int count = 0;
    for (int i=0; i<n; i++) {   
        pb = (node *)malloc(sizeof(LEN));         //新建一个结点
        //判断是否建立成功
        if (pb == NULL) {                       
            printf("Create Link failed\n");
            return NULL;
        }
        pb->data = ++count;                  //为新建结点的数据成员赋值


        //判断新建立的结点的位置,
        if (0 == i) {
            head = pb;                       //如果是第一个结点,则赋给head
            pf = pb;                         //新建的第一个结点也就是当前结点
        } else {
            pf->next = pb;                   //新建的结点为当前结点的下一个结点
        }
        pb->next = NULL;                     //为新建结点的next指针赋值

        pf = pb;                             //当前结点改为pb,为下一个结点创立做准备
    }
    pf->next = head;
    return head;
}

int main(void) {

    int sum = 41;
    int flag = 3;

    node *t, *h;      //h指向每次的起点        
                      //t指向要删除的点
    h = CreateLink(sum);

    while (h != h->next) {
        for (int i=1; i<flag-1; i++) {
            h = h->next;
        }

        t = h->next;//t为要删除的结点
        h->next = t->next;

        printf("%d ", t->data);//输出删除的数

        h = t->next;//新一轮开始 
    }
    printf("%d\n", h->data);
    return 0;
}
//修改版
#include <stdio.h> 
#include <stdlib.h>

typedef struct node {
    int data;
    struct node *next;
}node;

node *create(int n) {
    node *head;
    head = (node *)malloc(sizeof(node));

    int i=1;
    node *s,*p=head;
    while (i<=n) {
        s = (node*)malloc(sizeof(node));
        s->data = i++;
        p->next = s;
        p = p->next;
    }
    p->next = head->next;
    free(head);
    return p->next;
}

int main(void) {
    int i,n,m;
    node  *newstart,*h,*t;

    m=3;
    n=10;

    newstart=create(n);
    h=newstart;
    while(h!=h->next) {
        for(i=1;i<m-1;i++) {
            h=h->next;
        }
        t=h->next;
        printf("%d ",h->next->data);
        h->next=t->next;
        h=t->next;
        free(t);
        t = NULL;
    }
    printf("%d\n", h->data);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值