双向链表实现约瑟夫问题

news2024/11/25 16:48:09

title: 双向链表实现约瑟夫问题
date: 2023-05-16 11:42:26
tags:


  • **问题:**知n个人围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。

  • git地址:https://github.com/944613709/HIT-Data-Structures-and-Algorithms

    算法思想:

    \1. 构建n个结点的双向链表,初始化按照先后顺序给链表的每个节点data值赋值为i(代表是链表第i个)

    \2. 执行search函数,从Head开始寻找第P个节点,while循环head = head->next;直到来到第P个结点

    \3. 执行Jump函数,将从当前head的前m-1次结点进行正常报数,然后返回第m个结点

    \4. 对Jump函数返回来的第m个结点作为新head执行Delete语句,删除当前的结点,并且返回下一个节点,进行下一轮报数

    \5. 利用Delete函数返回来的结点作为新head,重复3,4操作

    \6. 上述重复操作总共执行n-1次出列之后,剩下最后一个人

    算法步骤:

    \1. 建立n个结点的双向链表

    (1) 定义一个Node *head作为头结点data赋值1,再定义一个Node *tail记录尾结点

    (2) For循环n-1次,for(int i=2;i<=len;i++)

    ① 定义Node *node,并且将data值赋值为当前的i

    ② 尾插法,将node插入链表

    \2. 执行search函数

    (1) 执行while循环直到第k个结点,while (head->data != k)

    ① head = head->next;

    (2) 返回第k个结点Return head

    \3. 利用while循环对jump和delete重复操作,同时利用count记录出列次数

    3.1 执行Jump函数

    (1) int count=0;利用count计数记录报数

    (2) While循环直到count=m-1

    ① Count++代表计数加1

    ② Printf执行报数

    ③ 让head指向下一位结点

    \1) 如果head此时已经指向尾结点,则while循环不断head=head->pre,直到head再次指向链表第一个节点

    \2) 如果head不指向尾结点,则head=head->next;即可

    (3) 返回结点Return head

    3.2执行Delete语句

    (4) Node *temp=head;

    (5) 执行printf,声明这个节点要被删除,分三种情况讨论

    ① 对于删除头节点(temp->pre == NULL),直接 head=head->next;然后temp->next=NULL;head->pre=NULL;free(temp); return head;

    ② 对于删除尾结点if(temp->next == NULL) ,利用while循环head=head->pre;,使得head跳到链表第一个,然后执行删除原尾结点temp->pre->next=NULL;temp->pre=NULL;free(temp);

    ③ 对于删除中间结点head=head->next; temp->pre->next=temp->next; temp->next->pre=temp->pre; free(temp);

    测试样例:

    img

    具体代码

    #include<stdio.h>

  **#include<stdlib.h>**

  **#include<math.h>**

  **int delTime=0;**

  **typedef struct Node**

  **{**

  ​     **int data;**

  ​     **struct Node \*pre;**

  ​     **struct Node \*next;**

  **}Node;**

  **Node\* CreatNode(int data)//****新建结点并赋值** 

  **{**

  ​     **Node \*node=(Node\*)malloc(sizeof(Node));**

  ​     **node->data=data;**

  ​     **node->pre=NULL;**

  ​     **node->next=NULL;**

  ​     **return node;**

  **}**

  **Node\* CreatList(int len)**

  **{**

  ​     **int num=1;**

  ​     **Node \*head= CreatNode(1);**

  ​     **Node \*tail=head;**

  ​     **for(int i=2;i<=len;i++)**

  ​     **{**

  ​          **Node \*node=CreatNode(i);**

  ​          **tail->next=node;**

  ​          **node->pre=tail;**

  ​          **tail=tail->next;**

  ​     **}**

  ​     **tail->next=NULL;**

  ​     **return head;**

  **}**

  **Node\* Delete(Node \*head)//****删除当前的,并且返回下一个节点,进行下一轮报数** 

  **{**

  ​     **Node \*temp=head;**

  ​     **delTime++;//****用以判断是否到删除的数** 

  ​     **printf("****本轮报数正好出列,第%d****次执行删除编号为%d\n",delTime,temp->data);**

  ​     **if(temp->pre == NULL)//****对于删除头节点** 

  ​      **{**

  ​      **head=head->next;**

  ​      **temp->next=NULL;**

  ​      **head->pre=NULL;**

  ​      **free(temp);**

  ​      **return head;**

  ​      **}**

   

  ​      **/\*****判断是否是尾节点\*/**

  ​      **else if(temp->next == NULL)//****对于删除尾结点** 

  ​      **{**

  ​           **while(head->pre!=NULL)**

  ​                 **head=head->pre;//****删除后head****跳到当前链表第一个** 

  ​        **temp->pre->next=NULL;**

  ​        **temp->pre=NULL;**

  ​        **free(temp);**

  ​        **return head;**

  ​      **}**

  ​      **else//****删除中间结点** 

  ​      **{**

  ​           **head=head->next;**

  ​        **temp->pre->next=temp->next;**

  ​        **temp->next->pre=temp->pre;**

  ​        **free(temp);**  

  ​        **return head;**  

  ​      **}**

  ​       

  **}** 

  **Node \*Search(Node \*head, int k) {  //****从Head****开始寻找第P****个节点**

  ​     **while (head->data != k) {**

  ​          **head = head->next;**

  ​     **}**

  ​     **return head;**

  **}**

  **Node \*Jump(Node \*head, int m)//****将head****前m-1****次正常报数,然后返回第m****次** 

  **{**

  ​     **int count=0;**

  ​     **while(count!=m-1)//****前m-1****个人都能正常报数**

  ​     **{**

  ​          **count++;**

  ​          **printf("****报数为->%d,****编号data****为->%d\n",count,head->data);//****报数** 

  ​          **if(head->next==NULL)**

  ​          **{**

  ​              **while(head->pre!=NULL)**

  ​                   **head=head->pre;**

  ​          **}//****换行** 

  ​          **else**

  ​              **head=head->next;**

  ​     **}**

  ​     **return head;** 

  **}**

  **int main()//****已知n****个人围坐在一张圆桌周围。从编号为k****的人开始报数,数到m****的那个人出列;他的下一个人又从1****开始报数,数到m****的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。(****摘自百度百科)**

  **{**

  ​     **int n,k,m;**

  ​     **int count=0;**

  ​     **printf("****按照n,k,m\n");**

  ​     **while(scanf("%d,%d,%d",&n,&k,&m)!=3)**

  ​     **{**

  ​     **}**

  ​     **Node \*head=CreatList(n);**

  ​     **head=Search(head,k);**

  ​     **while(count!=n-1)//****执行n-1****次出列,来完成剩下最后一个人**

  ​     **{**

  ​          **count++;**

  ​          **head=Jump(head,m);//****将head****前m-1****次正常报数,然后返回第m****次** 

  ​          **head=Delete(head);//****删除当前的,并且返回下一个节点,进行下一轮报数** 

  ​     **}**

  ​     **printf("****最后剩下的是编号为%d\n",head->data);**

  **}**

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/534527.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java进阶-Collection集合

1.Collection集合 1.1数组和集合的区别 相同点 都是容器&#xff0c;可以存储多个数据 不同点 数组的长度是不可变的&#xff0c;集合的长度是可变的 数组可以存基本数据类型和引用数据类型 集合只能存引用数据类型&#xff0c;如果要存基本数据类型&#xff0c;需要存对应的…

ubuntu20.04开机界面黑屏,只有一个光标闪烁

接下来我就把我的解决方法完整的发出来&#xff0c;因为我也是非常的绝望&#xff0c;终于在不断尝试中解决了问题 首先开机界面就是这个东西&#xff0c;一直卡在这不动了&#xff0c;原因就是&#xff0c;内存被用完了&#xff0c;无法加载出图形化界面 解决方法&#xff1…

springboot基于vue的MOBA类游戏攻略分享平台

系统分析 系统可行性分析 1、经济可行性 由于本系统本身存在一些技术层面的缺陷&#xff0c;并不能直接用于商业用途&#xff0c;只想要通过该系统的开发提高自身学术水平&#xff0c;不需要特定服务器等额外花费。所有创造及工作过程仅需在个人电脑上就能实现&#xff0c;使…

Redis学习--下载与安装

Redis下载与安装 Redis安装包分为windows版和Linux版&#xff1a; Windows版下载地址&#xff1a;https://github.com/microsoftarchive/redis/releases Linux版下载地址&#xff1a;https:/download.redis.io/releases 在Linux系统安装Redis步骤&#xff1a; 1.将Redis安装…

JENKINS部署-学习踩坑日记

1、JENKINS情况介绍 使用docker安装JENKINS&#xff0c;教程可以在网上搜到&#xff0c;步骤执行&#xff1b; 2、服务器情况介绍 JENKINS部署在A服务器上面&#xff0c;要把项目从gitlab上面拉取下来&#xff0c;然后编译推送jar到B服务器&#xff0c;然后通过docker-compose…

Linux:文本三剑客之sed编辑器

Linux&#xff1a;sed编辑器 一、sed1.1 sed编辑器1.2 sed编辑器的工作流程1.3 命令格式1.4常用选项1.5 常用操作1.6 实际应用 一、sed 1.1 sed编辑器 sed是一种流编辑器&#xff0c;流编辑器会在编辑器处理数据之前基于预先提供的一组规则来编辑数据流。sed编辑器可以根据命…

理解JVM

认识JVM Java 虚拟机&#xff08;JVM&#xff09;是运行 Java 字节码的虚拟机。 什么是字节码&#xff1f; 字节码就是jvm能理解的代码。即扩展名为 .class 的文件。 我们日常的java文件先编译成.class 文件 然后在jvm上运行。 个人觉得 内存区域是理解JVM相关的基石。所以彻…

微服务简介,SpringCloud Alibaba Nacos的安装部署与使用,Nacos集成springboot

目录 一.认识微服务 1.0.学习目标 1.1.单体架构 单体架构的优缺点如下&#xff1a; 1.2.分布式架构 分布式架构的优缺点&#xff1a; 1.3.微服务 微服务的架构特征&#xff1a; 1.4.SpringCloud 1.5Nacos注册中心 1.6.总结 二、Nacos基本使用 &#xff08;一&…

【C++】深入剖析C++11新特性

目录 一、C11简介 二、统一的列表初始化 1.&#xff5b;&#xff5d;初始化 2.std::initializer_list 三、声明 1.auto 2.decltype 3.nullptr 四、范围for 五、final和oberride 六、STL中一些变化 1.array 2.forward_list 3.unordered_map和unordered_set 七、右…

RabbitMQ养成记 (2. java操作MQ快速入门,日志监控,消息追踪)

快速入门 刚开始我们就一步一步来&#xff0c; 先搞什么spring集成。 先使用原始的java代码来操作一下MQ。 这里给新手兄弟的建议&#xff0c;这种技术性的学习 一定要先动手&#xff0c;从简单的地方动手&#xff0c;一步一步来&#xff0c;不然上来就搞理论或者复杂的应用很…

JDBC API

注册数据库驱动 Class.forName("com.mysql.jdbc.Driver"); 所谓的注册驱动&#xff0c;就是让JDBC程序加载mysql驱动程序&#xff0c;并管理驱动 驱动程序实现了JDBC API定义的接口以及和数据库服务器交互的功能&#xff0c;加载驱动是为了方便使用这些功能。 获…

Spring IOC相关注解运用——下篇

目录 一、Configuration 二、ComponentScan 1. 说明 2. 测试方法 3. 运行结果 三、PropertySource 1. 说明 2. 测试方法 3. 测试结果 四、Bean 1. 说明 2. 添加驱动依赖 3. 将Connection对象放入Spring容器 3. 测试 五、Import 1. 说明 2. 测试方法 3. 运行结…

从一道go逆向出发,讨论类tea的逆算法

tea代码很短&#xff0c;经常被直接复制为源码&#xff08;而不是像标准算法那样调库&#xff09;。在ctf逆向中也算比较常见&#xff0c;复杂度适中。 例题是一道go逆向&#xff0c;经go parser处理后&#xff0c;核心代码如下图。 panic算是go的专有名词&#xff0c;类似异常…

吃透 Spring AOP (1.理解概念)

理解 什么是AOP AOP&#xff0c;全称面向切面编程。 它可以说是对面向对象OOP的思想升华。从总的理解来讲&#xff0c;AOP是横向对不同程序的抽象。这个思想要不断实践动手之后&#xff0c;才会有很深刻的理解 理解 代理模式 在理解AOP之前&#xff0c;我们首先要单独说一个…

FFMPEG录屏(16)--- MAG(Magnification)捕获桌面

最近增加了对Magnification API捕获桌面的支持&#xff0c;记录一下过程和其中遇到的问题。 参考资料 Magnification API overview Magnification API sample webrtc screen_capturer_win_magnifier.cc Structured Exception Handling (C/C) 前言 我又不得不吐槽一下了&a…

【JavaWeb】-- HTTP、Tomcat、Servlet

文章目录 HTTP1.简介2.请求数据格式2.2.1 格式介绍 3.响应数据格式3.1 格式介绍3.2 响应状态码 Tomcat1.简介1.1 什么是Web服务器 2.基本使用2.1 安装2.2 启动2.3 关闭 3.Maven创建Web项目4.IDEA使用Tomcat4.1集成本地Tomcat4.2 Tomcat Maven插件 Servlet1.简介2.快速入门3.执行…

okhttp篇3:RealCall

Call Call一般代表一个已经准备好的Request&#xff0c;Request的包装类&#xff0c;可执行&#xff0c;它一般有两个主要的方法&#xff1a; execute(立即执行&#xff0c;并阻塞线程&#xff0c;直到Response返回)enqueue(将Request放入队列&#xff0c;等待线程池调度执行…

spring源码学习_01 本地环境搭建

参考网上各种资源&#xff0c;终于把spring源码运行起来了&#xff1b;步骤总结如下&#xff1a; spring版本&#xff1a; 5.2.x 本地系统mac idea 2019.3.2 下载地址&#xff1a;https://www.jetbrains.com/idea/download/other.html jdk 11 下载地址&#xff1a;https://repo…

【设计模式二十三剑】✨编写更高质量代码的秘诀✨

文章目录 ✨✨简述&#x1f386;【万能之门】简单工厂模式&#xff08;Simple Factory&#xff09;&#x1f387;【制造之剑】工厂方法模式&#xff08;Factory Method&#xff09;&#x1f387;【生产之剑】抽象工厂模式&#xff08;Abstract Factory&#xff09;&#x1f387…

C语言基础知识:函数的调用

函数的定义 一般来说&#xff0c;执行源程序就是执行主函数main&#xff0c;其他函数只能被主函数所调用&#xff0c;而其他函数之间也可以相互调用。 1.标准库函数&#xff1a; 分为&#xff1a;I/O函数&#xff0c;字符串&#xff0c;字符处理函数&#xff0c;数学函数&am…