约瑟夫环问题

举报
万里羊 发表于 2021/08/25 00:01:42 2021/08/25
【摘要】 问题描述 设有n个人围坐在圆桌周围,现从某个位置m(1≤m≤n)上的人开始报数,报数到k的 人就站出来。下一个人,即原来的第k+1位置上的人又从1开始报数,再报数到k的人站出来。依此重复下去,直到全部的...

问题描述

设有n个人围坐在圆桌周围,现从某个位置m(1≤m≤n)上的人开始报数,报数到k的
人就站出来。下一个人,即原来的第k+1位置上的人又从1开始报数,再报数到k的人站出来。依此重复下去,直到全部的人都站出来为止。试设计一个程序求出出列序列。

数据结构

循环单链表

算法分析与设计

这是一个使用循环链表的经典问题。因为要不断地出列,采用链表的存储形式能更好地模拟出列的情况。本算法即采用一个不带表头的循环链表来处理约瑟夫环问题,其中的n个人用n个结点来表示。程序有两个函数:
➢ 函数Create_ clist(): 用来创建-一个不带头结点的单循环链表,clist 为头指针,创建结束后让全局指针joseph指向循环链表的头。
➢ 函数Joseph():实现出列。

Joseph算法伪代码描述如下:

{
	初始化工作指针p=joseph;
	循环做p=p->next,直到p指向第m个结点(从m报数);
	while p
	{	
		循环做 p=p->next,直到p指向第k-1个结点:
		q=p->next,输出结点q的编号(输出数到k的人);
		if(p->next==p即链表中只有-一个结点)(数到k的人出列)
		删除p;
		else删除q;
	}
	链表指针clist置空;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

操作示意图

在这里插入图片描述
在此算法中,每次找出需出列的结点,要经过k次循环移动定位指针。全部结点出列
需经过n个k次循环
。因此,本算法的时间复杂度为O(k*n)。在实际问题的处理中,有许多与约瑟夫问题类似,都可以采用此方法完成。

程序实现

#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#define OVERFLOW -1
typedef int Elemtype;//定义数据元素类型
typedef struct Conode
{
    Elemtype data;
    struct Cnode *next;
}CNode;
CNode *joseph;//定义一个全局变量
//创建单循环链表
int Create_clist(CNode *clist,int n)
{
    CNode *p,*q;
    int i;
    clist=NULL;
    for(i=n;i>=1;i--)
    {
        p=(CNode *)malloc(sizeof(CNode));
        if(p==NULL) return OVERFLOW;//存储分配内存失败
        p->data=i;
        p->next=clist;
        clist=p;
        if(i==n) q=p;//用q指向链表的最后一个结点
    }
    q->next=clist;//把链表的最后一个结点的链域指向链表的第一个节点,构成循环链表
    joseph=clist;//把创建好的循环链表头指针赋给全局变量
    return 1;
}
int Joseph(CNode *clist,int m,int n,int k)
{
    int i;
    CNode *p,*q;
    if(m>n) return -1;//起始位置错误
    if(!Create_clist(clist,n))
        return -1;//循环链表创建失败
    p=joseph;//指向创建好的循环链表
    for(i=1;i<m;i++)
        p=p->next;//p指向m位置的节点
    while(p)
    {
        for(i=1;i<k-1;i++)
            p=p->next;//找出k-1个结点
        q=p->next;
        printf(" %d",q->data);//输出应出列的的节点
        if(p->next==p)
            p=NULL;//删除最后一个结点
        else{
            p->next=q->next; 
            p=p->next;
            free(q);
        }
    }
    clist=NULL;
    return 1;
}
int main()
{
    int m,n,k;
    CNode *clist;
    clist=NULL;
    printf("\n 请输入围坐在圆桌周围的人数n:");
    scanf("%d",&n);
    printf(" 请输入第一次开始报数人的位置m:");
    scanf("%d",&m);
    printf("你希望报数到第几个数的人出列?");
    scanf("%d",&k);
    Create_clist(clist,n);
    printf("出列结果如下:\n");
    Joseph(clist,m,n,k);
    printf("\n");
    return 0;
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75

在这里插入图片描述

文章来源: wlybsy.blog.csdn.net,作者:万里羊,版权归原作者所有,如需转载,请联系作者。

原文链接:wlybsy.blog.csdn.net/article/details/105903697

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。