C语言数据结构-用链表解决约瑟夫环问题

这篇具有很好参考价值的文章主要介绍了C语言数据结构-用链表解决约瑟夫环问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前记

只是普通的大学生一枚,不会很牛的技巧和算法,只是在做数据结构作业中的一点感悟和思考。也不知道自己写得对不对,有什么意见和建议都可以直接指出来哦,我虚心接受(低头鞠躬.jpg)......

题目

试用线性表的链表存储结构来实现约瑟夫(Josephu)问题。约瑟夫问题如下:设有n个人围坐圆桌周围。从某个位置上的人开始从1报数,数到m的人便出列,下一个人(第m+1个)又从1报数开始,数到m的人便是第2个出列的人,依次类推,直到最后一个人出列为止,这样就可以得到一个人员排列的新次序。例如,n=8,m=4,从第1个人数起,得到的新次序为48521376。

思路

首先刚开始的次序为1,2,3,...,7,8。从第一个人开始遍历,数到m,也就是第m个人就出去,先打印出列人的序号,再把这个结点从表中删除,继续遍历,继续找到下一个出列的人打印序号。如果用单链表解决的话,就出现了一个问题,遍历到尾结点时,无法继续报数了。所以此时需要用到循环单链表,将尾结点和头部连接起来。这样就能继续进行遍历。重复打印序号、删除结点操作,直到只剩下最后一个人。

函数代码

创建结点的结构体

typedef int ElemType;
typedef struct LNode  
{
    ElemType data;
    struct LNode *next;    
} LinkNode;    

创建循环单链表

void CreateList(LinkNode *&L,int n)  //创建循环单链表 
{
    LinkNode *s,*r;
    L=(LinkNode *)malloc(sizeof(LinkNode));  
    L->next=NULL;
    r=L;                
    for (int i=1;i<n;i++)  //这里从1开始循环是因为是从头结点的下一个结点开始赋值
    {    
        s=(LinkNode *)malloc(sizeof(LinkNode));
        s->data=i;
        r->next=s;            
        r=s;
    }
    r->next=L;     //尾结点连接到头结点   
    L->data=n;   //头结点赋值为最后一个数k
}

初始化单链表

void InitList(LinkNode *&L)    //初始化 
{
    L=(LinkNode *)malloc(sizeof(LinkNode)); 
    L->next=NULL;
}

打印链表

void DispList(LinkNode *L)   //打印 
{
    LinkNode *p=L->next;
    while ( p != L)  
    //因为是循环单链表,所以一直到指针移到头结点才结束循环
    {    
        printf("%d ",p->data);
        p=p->next;
    }
    printf("%d ",p->data);  //因为头结点存放的是最后一个值,所以单独打印出来
    printf("\n");
}

基本的一些函数就写完了,接下来开写重头戏——约瑟夫环。我习惯写在主函数里了......

主函数

int main()
{
    LinkNode *L,*p,*r;
    InitList(L);
    int num;           //圆桌上的总人数
    int outnum;        //喊到就要出列的数字
    printf("请输入具体坐在圆桌上的人数:"); 
    scanf("%d",&num);
    printf("请输入代表出列的数字:");
    scanf("%d",&outnum);
    CreateList(L,num);   //创建初始的次序链表
    printf("初始的人员次序为:");
    DispList(L);
    printf("出列的新人员次序为:"); 
    p = L->next;    //将指针指向头结点的下一个
    while (p->next != p)  
    //循环条件,因为最后剩下一个人的话,指针下一个指向的还是自身
    //所以当p->next = p时,循环结束。此时剩下最后一人。
    {
        for (int i = 1; i < outnum; i++)   //从第一个人开始依次报数、出列
        {
            r = p;       //r指针用来记录具体删除某结点后遍历的位置,为删除做准备
            p = p->next; 
        }
        //当循环结束时也就意味着找到了出列的人,此时p指向该出列序号,r指向前一个人
        printf("%d ", p->data);   //打印出列人的序号
        r->next = p->next;   
        p = p->next;    //删除p指向结点
    }
    printf("%d ", p->data);   //打印最后一人的序号
}

完整代码

#include <stdio.h>
#include <malloc.h>

typedef int ElemType;
typedef struct LNode  
{
    ElemType data;
    struct LNode *next;    
} LinkNode;                    

void CreateList(LinkNode *&L,int n) 
{
    LinkNode *s,*r;
    L=(LinkNode *)malloc(sizeof(LinkNode));  
    L->next=NULL;
    r=L;                
    for (int i=1;i<n;i++)
    {    
        s=(LinkNode *)malloc(sizeof(LinkNode));
        s->data=i;
        r->next=s;            
        r=s;
    }
    r->next=L;    
    L->data = n;
}

void InitList(LinkNode *&L)   
{
    L=(LinkNode *)malloc(sizeof(LinkNode)); 
    L->next=NULL;
}

void DispList(LinkNode *L)    
{
    LinkNode *p=L->next;
    while ( p != L)
    {    printf("%d ",p->data);
        p=p->next;
    }
    printf("%d ",p->data);
    printf("\n");
}

int main()
{
    LinkNode *L,*p,*r;
    InitList(L);
    int num;
    int outnum;
    printf("请输入具体坐在圆桌上的人数:"); 
    scanf("%d",&num);
    printf("请输入代表出列的数字:");
    scanf("%d",&outnum);
    CreateList(L,num);
    printf("初始的人员次序为:");
    DispList(L);
    printf("出列的新人员次序为:"); 
    p = L->next;
    while (p->next != p)
    {
        for (int i = 1; i < outnum; i++) 
        {
            r = p;
            p = p->next;
        }
        printf("%d ", p->data); 
        r->next = p->next;
        p = p->next;
    }
    printf("%d ", p->data);
}

你们看,我把注释都删了,多方便复制啊!!

输出结果

约瑟夫环c语言链表,链表,c语言,Powered by 金山文档

后记

刚开始一直写的是错的,输出前两个是4,8,第三个却不对,是3。后来我发现是因为我从最后一个结点到头结点的时候出现了问题,因为头结点本身也占用了位置,但是却没有数值,所以报到4的人出去,实际上我所写的出列的人是前一个人,紧跟着后面都错了。

后来上数据库的课程的时候(bushi我上课真的认真听讲了!),跟同桌讲了我出现的问题,后来突然灵光一闪,头结点占位置为啥不给它赋个值啊?这样一切就顺理成章啦!刚好能继续遍历,又不占位置。可能大佬都是一开始就能想到这个点,只有我这个小菜鸡想不清楚,搞好了之后开心得跟什么似的......

现在看来那根本就不算问题嘛!!文章来源地址https://www.toymoban.com/news/detail-739558.html

到了这里,关于C语言数据结构-用链表解决约瑟夫环问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构实验---顺序表的合并---链表的基本操作---重点解析约瑟夫问题

    实验的写法多种多样,但本文并未采用 #define 定义容量的写法,这样写已经是很老旧过时的写法。所有实验主体采用均为动态开辟,后续如果利用 C++ 来写或许会应用更多语法… 本篇展示数据结构的两个实验 其中,重点分析约瑟夫问题 实验中代码的命名风格等均与下方博客

    2024年02月16日
    浏览(61)
  • 数据结构—约瑟夫环问题(C语言版)

    目录 首先什么是约瑟夫环 约瑟夫环实现方式 一、创建结构体变量 二、初始化链表 三、构建循环链表 四、删除链表  五、完整代码及注释讲解 约瑟夫环 是 循环链表 中的一个经典问题;题目描述:n 个人围成一圈,从第一个人开始报数,数到 m 的人出列,再由下一个人重新

    2024年02月11日
    浏览(43)
  • C语言数据结构篇——约瑟夫环的实现

    作者名:Demo不是emo  主页面链接 : 主页传送门 创作初心: 对于计算机的学习者来说,初期的学习无疑是最迷茫和难以坚持的,中后期主要是经验和能力的提高,我也刚接触计算机1年,也在不断的探索,在CSDN写博客主要是为了分享自己的学习历程,学习方法,总结的经验等

    2023年04月08日
    浏览(36)
  • 【c语言习题】使用链表解决约瑟夫问题

    创作不易,本篇文章如果帮助到了你,还请点赞 关注支持一下♡𖥦)!! 主页专栏有更多知识,如有疑问欢迎大家指正讨论,共同进步! 🔥c语言系列专栏:c语言之路重点知识整合 🔥 给大家跳段街舞感谢支持!ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ 链表有

    2024年02月08日
    浏览(38)
  • 【数据结构】使用循环链表结构实现约瑟夫环问题

    目录 1.循环链表的定义 2.约瑟夫环问题 3.创建循环链表 4.删除节点操作 5.打印所有节点 6.实现约瑟夫环问题的完整程序代码 🌈嗨!我是Filotimo__🌈。很高兴与大家相识,希望我的博客能对你有所帮助。 💡本文由Filotimo__✍️原创,首发于CSDN📚。 📣如需转载,请事先与我联

    2024年01月18日
    浏览(40)
  • 数据结构与算法——约瑟夫环

    目录 一、例题引入         # 解题思路         #图例分析         #代码段         #题解小结  二、循环链表         分析:         直接看代码:  三、标记数组         分析:         代码: 四、递归算法          #沿用解释         设有n个人坐在圆桌周围,

    2024年02月08日
    浏览(44)
  • 数据结构实验1约瑟夫环

    刚开始m值为20 循环链表

    2024年02月08日
    浏览(42)
  • 重温数据结构与算法之约瑟夫问题

    约瑟夫问题 ,是一个计算机科学和数学中的问题,在计算机编程的算法中,类似问题又称为 约瑟夫环 ,又称“丢手绢问题”。 据说著名犹太历史学家 Josephus 有过以下的故事: 在罗马人占领乔塔帕特后,39个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也

    2024年02月08日
    浏览(46)
  • 数据结构学习-循环链表:处理约瑟夫环问题

    目录 问题描述 一、基本概念  1.普通链表 2.单向循环链表  二、问题处理 1.创建链表 2.查找 3.删除  4.其他  三.实验环节 四.总结 约瑟夫环问题的一种描述是:编号为1,2,...,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。一开始任选一个正整数作为报数

    2024年02月07日
    浏览(41)
  • 【数据结构与算法】约瑟夫环(C/C++)

    约瑟夫问题的一种描述是:编号为1,2,…,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。一开始任选一个正整数作为报数上限值m,从第一个人开始。按顺时针方向自1开始顺序报数,报到m时停止报数。报m的人出列,将他的密码作为新的m值,从他在顺时针方向上

    2024年02月12日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包