【数据结构与算法】约瑟夫环问题

约瑟夫环问题

由古罗马的史学家约瑟夫(Josephus)提出这样一个问题。问题描述为:编号为1, 2,… n的n个人按顺时针方向围坐在一张圆桌周围,每人持有一个密码(正整数)。一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始报数,报到m时停止报数,报m的那个人出列,将他的密码作为新的m值,从头开始重新从1报数,数到m的那个人又出列;如此下去,直至圆桌周围的人全部出列为止。

#示例

假定密码始终为2

img

输入:

​ 1 2

​ 2 2

​ 3 2

​ 4 2

​ 5 2

输出: 1 2

解释:因为每次从1开始数两个(包括1);

#include <stdio.h>
#include <stdlib.h>
typedef struct lp{
    int order;  //序号
    int digit;  //密码m
    struct lp *next;
}loop;

int make(loop *list);  //制作一个循环链表
void del(loop *list,int m,int *cnt);  //删除指定m的元素

int main(int argc,char const* argv[])
{
    int m;
    int cnt;    //记录有多少个节点
    loop *list = (loop*)malloc(sizeof(loop));
    list->next = NULL;
    printf("请输入序号和密码\n");
    cnt = make(list);
    
    printf("请输入一个密码m\n");
    scanf("%d",&m);
    del(list,m,&cnt);
    return 0;
}

int make(loop *list)
{
    int cnt;
    int n,n1;
    loop *now = list;
    while(scanf("%d %d",&n,&n1) != EOF)
    { 
        loop *p = (loop*)malloc(sizeof(loop));  //制作一个节点
        p->order = n;
        p->digit = n1;
        p->next = NULL;     
        while(now->next)
        {
            now = now->next;
        }
        now->next = p;
        cnt ++;            
    }
    /*表尾与表头的下一个节点连接*/
    now = now->next;
    now->next = list->next;

    return cnt;
}

void del(loop *list,int m,int *cnt)
{
    int number = 0;
    loop *i,*t;
    for(i = list->next,t = list; t; t=i,i=i->next)
    {
        number++;   //数的次数加一
        /*判断数的次数是不是与秘密相同,相同则释放掉对应节点内存*/
        if(number == m) 
        {
            t->next = i->next;
            m = i->digit;
            free(i);
            break;
        }
    }

    *cnt = *cnt - 1;    //每执行一次节点数减一

    /*当节点数等于1时输出对应的序号,密码*/
    if(*cnt > 1)
    {
       del(list,m,cnt); 
    }
    else{
        printf("保留的序号和密码为:\n");
        printf("%d\t%d\n",t->order,t->digit);
    }
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

摸鱼小小虫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值