约瑟夫环问题的思考

Posted GOAT_great

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了约瑟夫环问题的思考相关的知识,希望对你有一定的参考价值。

一.题目

编号为1~N的N个人按顺时针方向围坐一圈,每个人持有一个密码(正整数,可以自由输入),开始人选一个正整数做为报数上限值M,从第一个人按顺时针方向自1开始顺序报数,报到M时停止报数。报M的人出列,将他的密码作为新的M值,从他顺时针方向上的下一个人开始从1报数,如此下去,直到所有人出列为止。


二.问题分析


和约瑟夫问题不同的是,升级版多了一个密码,这个密码可以从线性表导入,也就是在创建结点时,有三个区域密码域password、数据域位置position、指针域next。

始化,再写游戏规则,在淘汰人时,依旧借助指针p遍历链表找到M位置的前一个,将指针域指向M处结点的下一个结点,即淘汰M处的结点,并将M的password作为新的M,继续上述步骤,直到全部淘汰。在游戏规则函数out中打印淘汰顺序。具体的在代码中有详细的注释。

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

typedef struct Node   

    int id;
    int password;
    struct Node*next;
Node;

Node* create_node(int x,int y)  //创建结点

    Node*p = NULL;
    p = (Node*)malloc(sizeof(Node));
    p->id =x;
    p->password = y;
    p->next = NULL;
    return p;


Node * Create_List(int n)    //创建无头链表录入信息

    Node*head = NULL;//创建头指针
    Node *tail,*pnew;//创建一个新结点指针P和尾指针tail
    int id,password;
    for(int i=1;i<=n;i++)
    
        printf("请输入第%d个人的密码",i);
        scanf("%d",&password);
        pnew = create_node(i,password);
        if(head==NULL)   //创建无头结点时要进行分类讨论
        
            head = pnew;//头指针指向第一个结点
            tail = pnew;//尾指针指向第一个结点
        
        else
        
            tail->next = pnew;   //尾指针的下一个指向新的结点
            tail = pnew;         //尾指针更新
        
    
    tail->next = head;
    printf("完成无头循环的建立");
    return head;

int IsEmptyList(Node*head) //判断无头链表是否为空

    if(!head)
    
        printf("This list is empty!");
        return 1;
    
    return 0;


void output(Node*head)  //输出无头链表


    Node*pmove = head;
    if(!IsEmptyList)
    
        printf("--ID-- --PASSWORD--\\n");
        do
        
            printf("%3d %7d\\n",pmove->id,pmove->password);
            pmove = pmove->next;
        while(pmove!=head);
    



void JosephusOperate(Node* head,int firstpassword)

    int icounter = 0;  //作用为辅助for循环
    int flag = 1;  //相当于Bool值,进行判断是否全部出队
    Node * tail,*point,*temp;  //tail和point两个指针进行一前一后双指针删除操作
    point = tail = head;     
    while(tail->next!=head)   //tail来指向尾结点
    
        tail = tail->next;   
    
    while(flag)    
    
        for(icounter = 1;icounter<firstpassword;icounter++)   //找到要出队的选手
        
            tail = point;
            point = point->next;
        
        if(point == tail) flag = 0;       //两个指针重合,说明队为空
        temp = point;                     //temp来记录要删除的结点
        tail->next = point->next;         //进行删除操作
        point= point->next;
        firstpassword = temp->password;
        printf("第%d个人出列(密码%d)\\n",temp->id,temp->password);
        free(temp);
    

    head = NULL;         // 此时队为空



int main()

    int n = 0,m = 0;
    printf("请输入人数:");
    scanf("%d",&n);
    printf("请输入初始密码:");
    scanf("%d",&m);
    Node *head = Create_List(n);
    printf("\\n------------打印单项循环链表-------------\\n");
    output(head);
    printf("\\n------------打印出队情况-------------\\n");
    JosephusOperate(head,m);
    return 1;


以上是关于约瑟夫环问题的思考的主要内容,如果未能解决你的问题,请参考以下文章

python类约瑟夫环原创问题求解 求大神

算法:约瑟夫环问题

约瑟夫环问题

约瑟夫环问题

用单向循环链表实现约瑟夫环问题

约瑟夫环问题