0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

C语言-有趣的约瑟夫问题及解决办法

嵌入式那些事 来源:嵌入式那些事 2023-09-23 11:13 次阅读

今天给大家讲讲约瑟夫问题是什么,并且我提供了一种约瑟夫问题的解决办法。对于不知道约瑟夫是谁的人来说,就更不用提什么是约瑟夫问题了。那么问题来了,约瑟夫是谁,约瑟夫问题又是个什么东西。

首先来个解释吧,约瑟夫问题,有时也称为约瑟夫置换,是一个出现在计算机科学和数学中的问题。特别是对于学习过数据结构的人来说,在书上看到解决这个问题的题目,可能都不下5遍吧。在计算机编程算法中,类似的问题又称为约瑟夫环或者丢手绢问题

约瑟夫(Josephus)是谁,约瑟夫是著名的犹太历史学家,那么约瑟夫问题又是个什么东西呢。其实我并不太清楚约瑟夫的什么生平经历,但是关于约瑟夫问题,倒是有一个小故事给大家讲一讲,这个故事就是约瑟夫问题的原型。好了,下面来个大家讲故事了,据说在罗马人占领乔塔帕特后,39个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus和他的朋友并不想遵从。首先从一个人开始,越过k-2个人(因为第一个人已经被越过),并杀掉第k个人。接着,再越过k-1个人,并杀掉第k个人。这个过程沿着圆圈一直进行,直到最终只剩下一个人留下,这个人就可以继续活着。问题是,给定了和,一开始要站在什么地方才能避免被处决?Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。

从上面的故事,大家至少可以知道,约瑟夫虽然是个历史学家,但是他的数学学的也不赖嘛。

约瑟夫问题并不难,求解的方法也非常的多,我这里提供一个循环链表的解决方法,为什么用循环链表,因为我看那个故事里面的人都是手拉手围成一个圆圈的嘛。

下面是我写的程序源代码,大家看看,就知道是怎么解决的了:

注:可以通过修改mian()函数中的StartCountlength这3个参数来改变游戏的规则,大家可以试试。

#include
#include

/*
*功能:约瑟夫问题解决办法(循环链表解决)
*By:AilsonJack
*Date:2014.05.24
*/
#defineerror0
#defineok1

typedefintElementType;
typedefstructCycleListNodeNode;
typedefstructCycleListNode*ptrNode;

structCycleListNode//循环链表结点
{
ElementTypedata;//数据区
ptrNodenext;//指向下一个结点
};

//函数声明
//约瑟夫问题解决办法(循环链表解决)
voidJosephus(ptrNodelist,intstart,intcount,intlength);

//创建循环链表头结点
intCycleList_CreateNode(ptrNode*list);

//初始化循环链表,并且最后丢掉链表头结点,链表的数据为1->length
voidCycleList_Init(ptrNode*list,intlength);

//删掉循环链表中从表头数的第position个位置的数据
//最终将头结点变为删除前那个结点的下一个结点
voidCycleList_Delete(ptrNode*list,intposition);

//查找循环链表中数据元素是Start的结点的位置,并且将该节点设为新的起始结点s
voidCycleList_Find(ptrNode*list,ElementTypeStart);

//打印循环链表中的数据
voidPrin_CycleList(ptrNodelist,intlength);

intmain(void)
{
intStart=1;//起始计数位置
intCount=3;//第Count个位置的结点出局
intlength=41;//循环链表的长度
ptrNodelist;

CycleList_CreateNode(&list);
CycleList_Init(&list,length);
Prin_CycleList(list,length);
Josephus(list,Start,Count,length);

while(1)
{
}

return0;
}

//约瑟夫问题解决办法(循环链表解决)
voidJosephus(ptrNodelist,intstart,intcount,intlength)
{
inti=1;

CycleList_Find(&list,start);
printf("
约瑟夫问题解决开始....
");

while(i<= length)
    {
        CycleList_Delete(&list,count);
i++;
}

printf("
约瑟夫问题解决结束
");
}

//创建循环链表头结点
intCycleList_CreateNode(ptrNode*list)
{
*list=(ptrNode)malloc(sizeof(structCycleListNode));
if(*list==NULL)
{
printf("OutofSpace...
");
returnerror;
}

(*list)->next=NULL;

returnok;
}//初始化循环链表,并且最后丢掉链表头结点,链表的数据为1->length
voidCycleList_Init(ptrNode*list,intlength)
{
inti=1;
ptrNodenewNode;
ptrNodeFirstNode;
FirstNode=*list;

while(i<= length)//i从1到length
{
newNode=(ptrNode)malloc(sizeof(structCycleListNode));
newNode->data=i;
(*list)->next=newNode;
(*list)=newNode;
i++;
}

(*list)->next=FirstNode->next;
*list=FirstNode->next;
}

//删掉循环链表中从表头数的第position个位置的数据
//最终将头结点变为删除前那个结点的下一个结点
voidCycleList_Delete(ptrNode*list,intposition)
{
inti=1;
ptrNodetmp;

if(position==1)
{
tmp=*list;
while(tmp->data!=(*list)->next->data)
{
*list=(*list)->next;
}
printf("%d",(*list)->next->data);
(*list)->next=tmp->next;
*list=tmp->next;
free(tmp);
tmp=NULL;
}
else
{
while(i< (position-1))
{
(*list)=(*list)->next;
i++;
}

tmp=(*list)->next;
printf("%d",tmp->data);
(*list)->next=(*list)->next->next;
free(tmp);
tmp=NULL;
*list=(*list)->next;
}
}

//查找循环链表中数据元素是Start的结点的位置,并且将该节点设为新的起始结点
voidCycleList_Find(ptrNode*list,ElementTypeStart)
{
while((*list)->data!=Start)
{
*list=(*list)->next;
}
}

//打印循环链表中的数据
voidPrin_CycleList(ptrNodelist,intlength)
{
inti=1;

printf("打印循环链表...
");

while(i<= length)
    {
        printf("%d",list->data);
list=list->next;
i++;
}

printf("
结束打印
");
}

下面是程序的运行结果:

345b147e-59b7-11ee-939d-92fbcf53809c.png

2015-03-31_165155

以上就是对约瑟夫问题的解决方法啦,大家有不明白的可以留言哟。


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • C语言
    +关注

    关注

    180

    文章

    7604

    浏览量

    136764
  • 函数
    +关注

    关注

    3

    文章

    4329

    浏览量

    62588
  • 数据结构
    +关注

    关注

    3

    文章

    573

    浏览量

    40127

原文标题:C语言-有趣的约瑟夫问题及解决办法

文章出处:【微信号:嵌入式那些事,微信公众号:嵌入式那些事】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    华硕笔记本声卡驱动无法安装的解决办法

    华硕笔记本声卡驱动无法安装的解决办法
    发表于 01-18 10:10 3545次阅读

    声卡硬件维修的常见问题及解决办法

    声卡硬件维修的常见问题及解决办法 常见故障一:声卡无声   出现这种故障常见的原因有:
    发表于 02-23 14:25 2554次阅读

    误码特性,误码产生的机理及解决办法

    误码特性,误码产生的机理及解决办法
    发表于 03-19 17:10 2267次阅读

    UPS电源输入跳闸浅析及解决办法

    UPS电源输入跳闸浅析及解决办法解析
    发表于 11-10 16:42 89次下载
    UPS电源输入跳闸浅析及<b class='flag-5'>解决办法</b>

    Matlab编程常见错误与解决办法

    Matlab编程常见错误与解决办法求人不如求己
    发表于 03-16 15:58 0次下载

    压榨辊轴承位磨损有哪些解决办法

    压榨辊轴承位磨损有哪些解决办法
    发表于 01-19 09:45 4次下载

    ESP32勘误表及解决办法

    电子发烧友网站提供《ESP32勘误表及解决办法.pdf》资料免费下载
    发表于 09-23 11:51 0次下载
    ESP32勘误表及<b class='flag-5'>解决办法</b>

    电脑右键管理打开失败的解决办法

    此电脑右键管理打不开怎么办 电脑右键管理打开失败的解决办法
    发表于 09-28 09:56 0次下载

    J-Link连接MCU失败解决办法

    J-Link连接MCU失败解决办法
    的头像 发表于 10-18 17:43 1098次阅读
    J-Link连接MCU失败<b class='flag-5'>解决办法</b>

    硬盘故障的3个终极解决办法

    电子发烧友网站提供《硬盘故障的3个终极解决办法.pdf》资料免费下载
    发表于 10-20 10:46 0次下载
    硬盘故障的3个终极<b class='flag-5'>解决办法</b>

    细碎机轴承位磨损问题的解决办法

    【设备故障】细碎机轴承位磨损问题的解决办法
    发表于 10-27 16:36 0次下载

    Protel99 与WIN10系统冲突解决办法

    PROTEL99 与WIN10系统冲突解决办法
    的头像 发表于 11-20 09:30 4102次阅读
    Protel99 与WIN10系统冲突<b class='flag-5'>解决办法</b>

    Profinet IO通信故障的解决办法

    Profinet IO通信故障可能由多种原因引起,以下是一些常见的通信故障及其解决办法
    的头像 发表于 03-08 11:27 1135次阅读

    常见MCU故障及解决办法

    微控制器单元(MCU)是现代电子设备中的核心组件,负责处理和控制各种功能。然而,由于各种原因,MCU可能会出现故障。以下是一些常见的MCU故障及其解决办法: 1. 电源问题 故障现象: MCU无法
    的头像 发表于 11-01 13:41 1633次阅读

    常见垫圈故障及解决办法 防漏垫圈的设计与应用

    常见垫圈故障及解决办法 1. 垫圈老化 故障现象: 垫圈因长时间使用而老化,失去弹性,导致密封性能下降。 解决办法: 定期检查垫圈的老化情况,及时更换新的垫圈。 2. 垫圈变形 故障现象: 由于安装
    的头像 发表于 12-12 15:31 252次阅读