老样子,先创建好结构体

typedef int datatype;typedef struct Node
{union{datatype data;  //节点数据域int len;  //长度};struct Node *next; //指针域
}Looplink;

辅助函数:

创建链表头函数:

//创建
Looplink *list_create()
{Looplink *L=(Looplink*)malloc(sizeof(Looplink));if(NULL == L){printf("创建失败\n");return NULL;}//初始化L->len=0;L->next=L;  //初始化时,头节点的指针域指向自己printf("创建成功\n");return L;}

以及一部分辅助函数

//判空
int list_empty(Looplink *L)
{return L->next==L? 1:0; //1表示空 0表示非空
}//节点申请函数
Looplink* node_add(datatype e)
{Looplink *p = (Looplink*)malloc(sizeof(Looplink));if(NULL == p){printf("节点申请失败\n");return NULL;}//数据存放p->data = e;p->next = NULL;
}

在主函数引导指定总数与步长,并存入循环链表

int m,n;printf("请制定数据总数:");scanf("%d",&m);printf("去指定选择步长:");scanf("%d",&n);Looplink *L = list_create();   //创建循环单向链表for(int i=0; i<m; i++){list_insert_tail(L, i+1);  //把数据用尾插法放入链表}

然后为了避免头节点影响遍历步长,故删除头节点

//删除头节点,使循环链表变成约瑟夫环Looplink *p = kill_head(L);   //删除头节点函数//遍历list_show2(p);/****************以下是用到的函数块*********************///链表断头
Looplink *kill_head(Looplink *L)
{//判断逻辑if(NULL==L || list_empty(L)){printf("删除失败\n");return NULL;}//定义遍历指针定位到最后一个节点Looplink *q = L->next;while(q->next != L){q=q->next;}//孤立头结点q->next=L->next;//删除头节点free(L);L=NULL;//返回第一个节点的位置printf("头结点删除成功\n");return q->next;
}
/***************************************/
//删除头节点的遍历
void list_show2(Looplink *S)
{//判断逻辑if(NULL==S){printf("遍历失败\n");return ;}//遍历printf("链表元素分别是\n");Looplink *q=S;do{printf("%d\t",q->data);q=q->next;}while(q!=S);printf("\n");
}

创建一个新的头,用以接受拆出来的链表元素

//创建一个新的头:SLooplink *S = list_create();

接下来,我们需要用指针p遍历链表,每四步断一次,然后把选中的元素,嫁接到新的链表头S上。同时要注意,

        一定不要把p直接放入嫁接函数!

        一定不要把p直接放入嫁接函数!

        一定不要把p直接放入嫁接函数!

重要的事情说三遍,不然会导致指针p指到只有一个元素的链表S内,导致段错误。故,应当设一个局部变量q,让它指向p,代替p进入嫁接函数。

//循环取值,逢n取1,到只剩一值时停下for(int i=0; i<m-1; i++ ){for(int j=0; j<n-1; j++)//因为P下面会多移一步,故步长为n-1{p = p->next;      }Looplink *q = p;   //工具人,让它去被拆掉,如果把p丢入函数,//会导致p指向只有一个元素的链表S,从而导致段错误p = p->next;list_reverse(S, q);   //拆除嫁接函数}list_reverse(S, p);       //把最后剩下的数嫁接到S上/*******************以下是使用到的相关函数***********************///拆出链表并嫁接
void list_reverse(Looplink *S ,Looplink *p)
{//查找前一个节点Looplink *q = find_node(p);        //前节点查找函数//孤立pq->next = p->next;p->next = NULL;//尾插法把p插入SLooplink *k=S;while(k->next != S){k=k->next;}p->next = S;k->next = p;//S->len++;printf("尾插成功\n");
}/********************上一个函数用到的节点查找函数************/
//查找上一个结点
Looplink *find_node(Looplink *L)
{//查找节点Looplink *q = L;while(q->next != L)   //当q下一位是L时停止{q = q->next;}return q;  //返回找到的节点
}

此时,我们已经得到了一个新的循环链表,只需要断掉最后一个元素与头节点S的连接,就能得到一个崭新出厂的顺序链表S了

//断开S与最后一位的链接Looplink *q=S;while(q->next != S){q = q->next;}q->next = NULL;//遍历S,检验结果list_show(S);return 0;/**********************顺序链表的遍历函数*******************/
//遍历
void list_show(Looplink *L)
{if(NULL == L || list_empty(L))  //先判断非法{printf("表空或表非法,遍历失败\n");return;}//遍历printf("链表元素为:");Looplink *q = L->next;while(q != NULL){printf("%d\t",q->data);q = q->next;}printf("\n");
}

至此,我们便完成了这个问题

以下张贴完整代码,酌情观看。

/**********************main.c********************/
//主函数#include<stdio.h>
#include<string.h>
#include"ysf.h"
int main(int argc, const char *argv[])
{int m,n;printf("请制定数据总数:");scanf("%d",&m);printf("去指定选择步长:");scanf("%d",&n);Looplink *L = list_create();   //创建循环单向链表for(int i=0; i<m; i++){list_insert_tail(L, i+1);  //把数据用尾插法放入链表}//删除头节点,使循环链表变成约瑟夫环Looplink *p = kill_head(L);//遍历list_show2(p);//创建一个新的头:SLooplink *S = list_create();//循环取值,逢n取1,到只剩一值时停下for(int i=0; i<m-1; i++ ){for(int j=0; j<n-1; j++)//因为P下面会多移一步,故步长为n-1{p = p->next;}Looplink *q = p;   //工具人,让它去被拆掉p = p->next;list_reverse(S, q);}list_reverse(S, p);//断开S与最后一位的链接Looplink *q=S;while(q->next != S){q = q->next;}q->next = NULL;//遍历S,检验结果list_show(S);return 0;
}

功能函数文件

/**********************ysf.h*******************/#include<stdio.h>
#include<stdlib.h>
#include"ysf.h"
//创建
Looplink *list_create()
{Looplink *L=(Looplink*)malloc(sizeof(Looplink));if(NULL == L){printf("创建失败\n");return NULL;}//初始化L->len=0;L->next=L;  //初始化时,头节点的指针域指向自己printf("创建成功\n");return L;}//判空
int list_empty(Looplink *L)
{return L->next==L? 1:0; //1表示空 0表示非空
}//节点申请函数
Looplink* node_add(datatype e)
{Looplink *p = (Looplink*)malloc(sizeof(Looplink));if(NULL == p){printf("节点申请失败\n");return NULL;}//数据存放p->data = e;p->next = NULL;
}//查找上一个结点
Looplink *find_node(Looplink *L)
{//查找节点Looplink *q = L;while(q->next != L){q = q->next;}return q;  //返回找到的节点
}//循环链表的尾插法
int list_insert_tail(Looplink *L,datatype e)
{//判断if(NULL==L){printf("所给链表不合法\n");return -1;}//申请节点Looplink *p = node_add(e);//插入逻辑Looplink *q=L;while(q->next != L){q = q->next;}p->next=L;q->next=p;//表的变化L->len++;printf("尾插成功\n");
}//链表断头
Looplink *kill_head(Looplink *L)
{//判断逻辑if(NULL==L || list_empty(L)){printf("删除失败\n");return NULL;}//定义遍历指针定位到最后一个节点Looplink *q = L->next;while(q->next != L){q=q->next;}//孤立头结点q->next=L->next;//删除头节点free(L);L=NULL;//返回第一个节点的位置printf("头结点删除成功\n");return q->next;
}//拆出链表并嫁接
void list_reverse(Looplink *S ,Looplink *p)
{//查找前一个节点Looplink *q = find_node(p);//孤立q->next = p->next;p->next = NULL;//尾插法把p插入SLooplink *k=S;while(k->next != S){k=k->next;}p->next = S;k->next = p;//S->len++;printf("尾插成功\n");
}//遍历
void list_show(Looplink *L)
{if(NULL == L || list_empty(L))  //先判断非法{printf("表空或表非法,遍历失败\n");return;}//遍历printf("链表元素为:");Looplink *q = L->next;while(q != NULL){printf("%d\t",q->data);q = q->next;}printf("\n");
}//删除头节点的遍历
void list_show2(Looplink *S)
{//判断逻辑if(NULL==S){printf("遍历失败\n");return ;}//遍历printf("链表元素分别是\n");Looplink *q=S;do{printf("%d\t",q->data);q=q->next;}while(q!=S);printf("\n");
}

最后是头文件

#ifndef __YSF__
#define __YSF__typedef int datatype;typedef struct Node
{union{datatype data;  //节点数据域int len;  //长度};struct Node *next; //指针域
}Looplink;//创建
Looplink *list_create();//查找上一个节点
Looplink *find_node(Looplink *L);//判空
int list_empty(Looplink *L);//节点申请函数
Looplink* node_add(datatype e);//尾插
int list_insert_tail(Looplink *L,datatype e);//链表断头
Looplink *kill_head(Looplink *L);//拆出链表并嫁接
void list_reverse(Looplink *S ,Looplink *p);//遍历
void list_show(Looplink *L);//删除头节点的遍历
void list_show2(Looplink *S);#endif

循环链表——约瑟夫环问题相关推荐

  1. 链表基础操作 / 循环链表约瑟夫环/STL链表基本操作

    链表的基础操作 程序功能 输入几 就把几调到数最前面 程序步骤: 1.插入函数 2.初始化函数 3.删除节点 4.把排列展示出来 程序注意 不同函数的指针 不同 头指针定义为全局变量 代码实现截图 # ...

  2. 循环链表(约瑟夫环)的建立及C语言实现

    约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3-n分别表示)围坐在一张圆桌周围.从编号为k的人开始报数,数到m的那个人出列:他的下一个人又从1开始报数,数到m的那个人又出列: ...

  3. Algorithms_基础数据结构(04)_线性表之链表_单向循环链表约瑟夫环问题

    文章目录 大纲图 链表的经典面试题目 如何设计一个LRU缓存淘汰算法 约瑟夫问题 结构 分析 大纲图 链表的经典面试题目 如何设计一个LRU缓存淘汰算法 tip:单向链表 约瑟夫问题 N个人围成一圈, ...

  4. 约瑟夫环 单向循环链表实现

    约瑟夫环 已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围.从编号为k的人开始报数,数到m的那个人出列:他的下一个人又从1开始报数,数到m的那个人又出列:依此规律重复下去,直到圆桌周围 ...

  5. 约瑟夫环之循环链表实现

    约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围.从编号为k的人开始报数,数到m的那个人出列:他的下一个人又从1开 始报数,数到m的那个人又出列:依此规律 ...

  6. python约瑟夫环单向循环链表_约瑟夫环的单向循环链表的实现代码

    /************************************************************************* > File Name: JosephCir ...

  7. 循环链表解决约瑟夫环问题

    约瑟夫环问题可以简单的使用数组的方式实现,但是现在我使用循环链表的方法来实现,因为上午看到一道面试题规定使用循环链表解决约瑟夫环问题. 什么是约瑟夫环? "约瑟夫环是一个数学的应用问题:已知 ...

  8. 约瑟夫环-(数组、循环链表、数学)

    约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围.从编号为k的人开始报数,数到m的那个人出列:他的下一个人又从1开始报数,数到m的那个人又出 ...

  9. 《恋上数据结构第1季》单向循环链表、双向循环链表以及约瑟夫环问题

    循环链表(CircleList) 链表的接口设计 单向循环链表 单向循环链表完整源码 双向循环链表 双向循环链表完整源码 双向循环链表解决约瑟夫环问题 如何发挥循环链表的最大威力? 静态链表 数据结构 ...

最新文章

  1. R语言sys方法:sys.getpid函数获取R会话的进程ID、sys.glob函数和file.path函数匹配文件夹下的所有特定类型文件、sys.info函数获取系统和用户信息
  2. 【mysql dump】 备份原理及脚本
  3. 字节跳动内部学习资料泄露!kafka入门教程
  4. python是不是特别垃圾-震惊!垃圾分类居然能用Python搞定!
  5. 的计时器设置_【教程】PPT课件中常见的计时器效果(2)——沙漏式计时器 | 源文件提供下载...
  6. Python 工具——Anaconda+Pycharm 的安装过程
  7. AI单挑Dota 2世界冠军:被电脑虐哭……
  8. php中写salt,请快速检查这个PHP+SALT实现-不工作?
  9. VCL组件之TPanel
  10. 集成学习—Adaboost(论文研读)
  11. MATLAB系统辨识
  12. 通过APKIDE 反编译文件得到.java文件方法
  13. Spark集群环境搭建+Maven、SBT编译部署+IDEA开发(二)
  14. linux权限后面的点,linux 文件权限后面一个点的含义
  15. redis主从、哨兵、集群
  16. [ant design vue] 表单验证成功,提示信息不显示
  17. 华为用c还是java,C语言和Java孰轻孰重!
  18. Windows 7系统实用进阶技巧
  19. v-model和v-bind
  20. 打印机耗材的发展趋势

热门文章

  1. 微博项目---项目介绍
  2. 利用外泌体研制抗肿瘤疫苗
  3. Message的使用
  4. fileinput的使用
  5. RestEasy简介
  6. 基于深度学习的目标检测综述(一):简介及骨干网络
  7. MySQL通过数据文件恢复数据库
  8. java jdbctype_JdbcType类型和Java类型的对应关系
  9. java 单例模式 ---饿汉式懒汉式
  10. kotlin与java混合开发_使用kotlin和Java混合开发Android项目爬坑记录