当前位置: 首页 > news >正文

【C语言】 约瑟夫环,循环链表实现

        
        更新一下,昨天的代码有点问题,没有考虑到头结点的影响,我的方法是:

        在进行步数位移的时候判断标记点,如果走到了头结点,就在循环里面立即往后再位移一次,把头结点跳过;同时在后面删除元素的时候,再次判断位移点有不有走到头结点,如果走到了的话,就直接再往后移动一位,这样就成功跳过头结点了

        单独拎出来约瑟夫环实现代码,函数封装


//约瑟夫
int link_yue(NodePtr L, int flag) {if (L == NULL || flag <= 0 || link_empty(L)) {printf("输入的参数有误或链表为空。\n");return -1;}NodePtr prev = L; NodePtr curr = L->next; while (L->len > 1) { for (int count = 0; count < flag-1; count++) {prev = curr; curr = curr->next; if(curr == L)              //在这里加入了一个if判断条件,判断在位移的时候有不有经过头节点,经过就跳过{prev = curr;curr = curr->next;}}printf("删除节点的值为: %d\n", curr->data); prev->next = curr->next; NodePtr temp = curr; curr = curr->next; if(curr == L)                 //在这里再加入了一个if判断条件,这个是用来判断删除之后节点有不有走到头结点,走到头结点,就跳过这个节点,跳过的方法是继续往后位移一位就行{prev = curr;curr = curr->next;}L->len--; free(temp); }// 输出最后剩下的节点数据printf("最后剩下的节点数据是:%d\n", curr->data);return 0;
}

以下为源码,分文件编译

1、循环链表实现约瑟夫环,每次经过特定步数删除一个元素

//looplist.h
#ifndef LOOPLIST_H
#define LOOPLIST_H
#include<stdio.h>
#include<string.h>
#include<stdlib.h>typedef int datatype;typedef struct Node
{union {int len;datatype data;};struct Node *next;
}Node,*NodePtr;//创建循环链表
NodePtr link_create();//判空
int link_empty(NodePtr L);//链表申请空间封装节点
NodePtr apply_node(datatype e);//按位置进行查找
NodePtr list_search_pos(NodePtr L, int pos);//头插
int link_insert_tail(NodePtr L,datatype e);//遍历链表
int link_show(NodePtr L);//约瑟夫
int link_yue(NodePtr L,int flag);
#endif
//looplist.c
#include"looplist.h"//创建循环链表
NodePtr link_create()
{NodePtr L = (NodePtr)malloc(sizeof(Node));if(NULL == L){printf("链表创建失败\n");return NULL;}L->len = 0;L->next = L;printf("创建链表成功\n");return L;
}//判空
int link_empty(NodePtr L)
{return L->next == L;
}//链表申请空间封装节点
NodePtr apply_node(datatype e)
{//堆区申请一个节点的空间NodePtr p = (NodePtr)malloc(sizeof(Node));if(NULL == p){printf("申请失败\n");return NULL;}//给节点赋值p->data = e;p->next = NULL;return p;
}//按位置进行查找
NodePtr list_search_pos(NodePtr L, int pos)
{if(NULL == L || pos < 0 || pos > L->len){printf("查找失败\n");return NULL;}NodePtr q = L;for (int  i = 0; i < pos; i++){q = q->next;}return q;
}//尾插
int link_insert_tail(NodePtr L,datatype e)
{   if(NULL == L){printf("插入失败\n");return -1;}NodePtr q = list_search_pos(L,L->len);NodePtr p = apply_node(e);p->next = q->next;q->next = p;L->len++;printf("插入成功\n");return 0;
}//遍历链表
int link_show(NodePtr L)
{if(NULL == L || link_empty(L)){printf("遍历失败\n");return -1;}NodePtr q = L->next;while(q != L){printf("%d\t",q->data);q = q->next;}printf("\n");
}//约瑟夫
int link_yue(NodePtr L, int flag) {if (L == NULL || flag <= 0 || link_empty(L)) {printf("输入的参数有误或链表为空。\n");return -1;}NodePtr prev = L; NodePtr curr = L->next; while (L->len > 1) { for (int count = 0; count < flag-1; count++) {prev = curr; curr = curr->next; if(curr == L)              //在这里加入了一个if判断条件,判断在位移的时候有不有经过头节点,经过就跳过{prev = curr;curr = curr->next;}}printf("删除节点的值为: %d\n", curr->data); prev->next = curr->next; NodePtr temp = curr; curr = curr->next; if(curr == L)                 //在这里再加入了一个if判断条件,这个是用来判断删除之后节点有不有走到头结点,走到头结点,就跳过这个节点,跳过的方法是继续往后位移一位就行{prev = curr;curr = curr->next;}L->len--; free(temp); }// 输出最后剩下的节点数据printf("最后剩下的节点数据是:%d\n", curr->data);return 0;
}
//main.c
#include"looplist.h"
int main(int argc, char const *argv[])
{NodePtr L = link_create();int flag = 0,n = 0,sum = 0;printf("请输入你想输入的个数:");scanf("%d",&n);//循环插入值for(int i = 0;i < n;i++){printf("请输入第%d个值:",i+1);scanf("%d",&sum);link_insert_tail(L,sum);}printf("当前链表中的元素为:");link_show(L);printf("请输入你想走多少步移除一个数:");scanf("%d",&flag);getchar();//调用约瑟夫环函数link_yue(L,flag);return 0;
}

 输出结果如下:

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 一个定期自动更换特定账号的密码的脚本
  • Android、Java反编译工具JADX
  • CSI-RS在信道中传输的过程
  • 使用脚本搭建MySQL数据库基础环境
  • JavaScript函数学习笔记[Web开发]
  • ts -> class -> abstract
  • CID引流-拼多多案例
  • 前端系列-7 Vue3响应式数据
  • 【简历】吉林某一本大学:JAVA秋招简历指导,简历通过率比较低
  • maven archetype
  • LeetCode 热题 HOT 100 (011/100)【宇宙最简单版】
  • 代码随想录算法训练营DAY64|拓扑排序、dijkstra(朴素版)
  • 基因组挖掘指导天然药物分子的发现-文献精读34
  • MongoDB教程(十五):MongoDB原子操作
  • 【系列专题】新质生产力之光,照亮“制造强国”之路
  • Effective Java 笔记(一)
  • es6要点
  • Netty源码解析1-Buffer
  • node.js
  • Node项目之评分系统(二)- 数据库设计
  • Quartz实现数据同步 | 从0开始构建SpringCloud微服务(3)
  • rc-form之最单纯情况
  • V4L2视频输入框架概述
  • vue:响应原理
  • 后端_MYSQL
  • 机器学习学习笔记一
  • 入口文件开始,分析Vue源码实现
  • 实战|智能家居行业移动应用性能分析
  • 算法-插入排序
  • 小程序测试方案初探
  • C# - 为值类型重定义相等性
  • ionic异常记录
  • mysql 慢查询分析工具:pt-query-digest 在mac 上的安装使用 ...
  • ​​​​​​​​​​​​​​汽车网络信息安全分析方法论
  • ​力扣解法汇总1802. 有界数组中指定下标处的最大值
  • ###C语言程序设计-----C语言学习(3)#
  • $.ajax()方法详解
  • (C语言)fgets与fputs函数详解
  • (LeetCode 49)Anagrams
  • (附源码)springboot 校园学生兼职系统 毕业设计 742122
  • (附源码)springboot美食分享系统 毕业设计 612231
  • (附源码)SSM环卫人员管理平台 计算机毕设36412
  • (简单) HDU 2612 Find a way,BFS。
  • (力扣)循环队列的实现与详解(C语言)
  • (十三)Flask之特殊装饰器详解
  • (四)js前端开发中设计模式之工厂方法模式
  • (一) 初入MySQL 【认识和部署】
  • (一)搭建springboot+vue前后端分离项目--前端vue搭建
  • (转)全文检索技术学习(三)——Lucene支持中文分词
  • (转贴)用VML开发工作流设计器 UCML.NET工作流管理系统
  • .gitignore文件使用
  • .NET Remoting学习笔记(三)信道
  • .NET 事件模型教程(二)
  • .netcore如何运行环境安装到Linux服务器
  • .NET编程C#线程之旅:十种开启线程的方式以及各自使用场景和优缺点