约瑟夫环问题(C语言实现)

编号为1,2,…,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。一开始任选一个整数作为报数上限值m,从第一个人开始顺时针自1开始顺序报数,报到m时停止报数。报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有的人全部出列为止。试设计一个程序,求出出列顺序。

**基本要求及提示**

(1) 利用单向循环链表作为存储结构模拟此过程。

(2) 按照出列顺序打印出各人的编号。 例如m的初值为20;n=7,7个人的密码依次是:3,1,7,2,4,8,4,出列的顺序为6,1,4,7,2,3,5。

(3) 要求程序通过一个主菜单进行控制,在主菜单界面通过选择菜单项的序号来调用各功能函数。

代码实现

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#define scanf_s scanf

#define ERROR 0

#define OK 1

#define FALSE -1

#define TRUE 1

typedef struct NODE

{

    int i;

    int num;

    struct NODE *next;

}NODE;

int menu_select(); // 菜单驱动程序

void introduce(); // 介绍

void createList(NODE **L,int e); // 创建约瑟夫环

void out(NODE *L,int e); // 输出结果

NODE *createNode(int a,int b); // 创建结点

int menu_select() // 菜单驱动程序

{

    int sn;

    printf("       约瑟夫环问题  \n"); // 显示菜单

    printf("==============================\n");

    printf("   1、约瑟夫环介绍\n");

    printf("   2、按要求求解约瑟夫环\n");

    printf("   0、退出\n");

    printf("==============================\n");

    printf("  请选择0--2:  ");

    for(;;) // 菜单功能选择

    {

        scanf("%d",&sn);

        getchar();

        if(sn<0 || sn>2)

            printf("\n\t 输入选择错误,请重新选择 0--6: ");

        else

            break;

    }

    return sn;

}

void introduce()

{

    printf("                                    约瑟夫问题\n");

    printf("编号为1,2....n的n个人按顺时针方向围坐一圈,每人各持有一个密码(正整数)。一开始任选一正整数作为报数上限值m,从第一个人开始顺时针自开始顺序报数,报到m时停止报数。报m的人出列,将它的密码作为新的m值,从他在顺时针的方向上的下一个人开始重新从报数,如此下去,直到所有的人全部出列为止。\n");

}

void createList(NODE **L,int e)

{

    int i,key;

    NODE *p,*q;

    for(i=1;i<=e;i++)

    {

        printf("请输入第%d个人的密码:",i);

        scanf("%d",&key);

        p=createNode(i,key);

        if(*L==NULL)

        {

            *L=q=p;

            q->next=*L;

        }

        else

        {

            p->next=q->next;

            q->next=p;

            q=p;

        }

    }

    printf("创建完毕。\n");

}

/*

TODO: 按照出列顺序打印出各人的编号。

例如m的初值为20;n=7,7个人的密码依次是:3,1,7,2,4,8,4,出列的顺序为6,1,4,7,2,3,5。

方法用到输出语句,打印第几个出列,密码是多少: printf("第%d 个人出列,密码为%d\n",L->i,L->num);

打印信息例如: 第6 个人出列,密码为3

*/

void out(NODE *L,int e)

{

    int t=1,flag;

    NODE *p1=L;

    while(L->next!=L)

    {

        if(t==e-1)p1=L;

        if(t==e)

        {

            printf("第%d 个人出列,密码为%d\n",L->i,L->num);

            flag=L->num;

        }

        if(t==e+1)

        {

            p1->next=L;

            t=1;

            e=flag;

            continue;

        }

        L=L->next;

        t++;

    }

    printf("第%d 个人出列,密码为%d\n",L->i,L->num);

}

NODE *createNode(int a,int b)

{

    NODE *p;

    p=(NODE*)malloc(sizeof(NODE));

    p->i=a;

    p->num=b;

    p->next=NULL;

    return p;

}

void main()

{

   int m,n;

    NODE *head;

    head=NULL;

    for(;;) // 无限循环,选择0 退出

    {

        switch( menu_select()) // 调用菜单函数,按返回值选择功能函数

        {

            case 1: introduce();

                break;

        case 2: printf("请输入总人数n:");

                scanf_s("%d",&n);

                printf("请输入开始报数上限值m: ");

                scanf_s("%d",&m);

                createList(&head,n);

                printf("\n");

                printf("出列顺序:\n");

                out(head,m);

                printf("结束.\n");

                break;

        case 0: printf("再见\n");

                return;

        } // switch语句结束

    } // for循环结束

} // main()函数结束

  • 3
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值