链表的使用,还可以把链表的两头连接,形成了一个环状链表,称为循环链表。

和它名字的表意一样,只需要将表中最后一个结点的指针指向头结点,就形成了一个环。

图1 循环链表
循环链表和动态链表相比,唯一的不同就是循环链表首尾相连,其他都完全一样。

实际应用:约瑟夫环问题

约瑟夫环问题,是一个经典的循环链表问题,题意是:已知 n 个人(以编号1,2,3,…,n分别表示)围坐在一张圆桌周围,从编号为 k 的人开始顺时针报数,数到 m 的那个人出列;他的下一个人又从 1 还是顺时针开始报数,数到 m 的那个人又出列;依次重复下去,要求找到最后出列的那个人。

例如有 5 个人,要求从编号为 3 的人开始,数到 2 的那个人出列:

出列顺序依次为:

编号为 3 的人开始数 1,然后 4 数 2,所以 4 先出列;
4 出列后,从 5 开始数 1,1 数 2,所以 1 出列;
1 出列后,从 2 开始数 1,3 数 2,所以 3 出列;
3 出列后,从 5 开始数 1,2 数 2,所以 2 出列;
最后只剩下 5 自己,所以 5 出列。

完整代码

#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
  int number;
  struct node *next;
}person;
person *initLink(int n)
{
  person * head = (person*)malloc(sizeof(person));
  head->number = ;
  head->next = NULL;
  person *cyclic = head;
  for (int i=; i<=n; i++)
  {
    person *body = (person*)malloc(sizeof(person));
    body->number = i;
    body->next = NULL;
    cyclic->next = body;
    cyclic = cyclic->next;
  }
  cyclic->next = head;  //首尾相连
  return head;
}
void findAndKillK(person *head, int k, int m)
{
  person *tail = head;
  //找到链表第一个结点的上一个结点,为删除操作做准备
  while (tail->next != head)
  {
    tail = tail->next;
  }
  person *p = head;
  //找到编号为k的人
  while (p->number!=k)
  {
    tail=p;
    p=p->next;
  }
  //从编号为k的人开始,只有符合p->next==p时,说明链表中除了p结点,所有编号都出列了,
  while (p->next!=p)
  {
    //找到从p报数1开始,报m的人,并且还要知道数m-1de人的位置tail,方便做删除操作。
    for (int i=; i<m; i++)
    {
      tail = p;
      p = p->next;
    }
    tail->next = p->next;  //从链表上将p结点摘下来
    printf("出列人的编号为:%d\n", p->number);
    free(p);
    p = tail->next;//继续使用p指针指向出列编号的下一个编号,游戏继续
  }
  printf("出列人的编号为:%d\n", p->number);
  free(p);
}
int main()
{
  printf("输入圆桌上的人数n:");
  int n;
  scanf("%d", &n);
  person *head = initLink(n);
  printf("从第k人开始报数(k>1且k<%d):", n);
  int k;
  scanf("%d", &k);
  printf("数到m的人出列:");
  int m;
  scanf("%d", &m);
  findAndKillK(head, k, m);
  return ;
}
输出结果:
输入圆桌上的人数n:
从第k人开始报数(k>1且k<):
数到m的人出列:
出列人的编号为:
出列人的编号为:
出列人的编号为:
出列人的编号为:
出列人的编号为:

总结

循环链表和动态链表唯一不同在于它的首尾连接,这也注定了在使用循环链表时,附带的最多的操作就是遍历链表。

在遍历的过程中,尤其要注意循环链表虽然首尾相连,但并不表示该链表没有第一个节点和最后一个结点。所以,不要随意改变头指针的指向。

数据结构7: 循环链表(约瑟夫环)的建立及C语言实现的更多相关文章

  1. 约瑟夫环(N个人围桌,C语言,数据结构)

    约瑟夫环问题(C语言.数据结构版) 一.问题描述 N个人围城一桌(首位相连),约定从1报数,报到数为k的人出局,然后下一位又从1开始报,以此类推.最后留下的人获胜.(有很多类似问题,如猴子选代王等等, ...

  2. 约瑟夫环问题-循环链表VS数组

    2013-08-18 21:27:50 循环链表.数组解决约瑟夫环问题的比较 注意几点: 循环链表的建立不难,在删除循环链表中元素时,用pCur->next != pCur判断结束: 每一轮计数 ...

  3. 数据结构8: 双向链表(双向循环链表)的建立及C语言实现

    之前接触到的链表都只有一个指针,指向直接后继,整个链表只能单方向从表头访问到表尾,这种结构的链表统称为 “单向链表”或“单链表”. 如果算法中需要频繁地找某结点的前趋结点,单链表的解决方式是遍历整个链 ...

  4. javascript中使用循环链表实现约瑟夫环问题

    1.问题 传说在公元1 世纪的犹太战争中,犹太历史学家弗拉维奥·约瑟夫斯和他的40 个同胞被罗马士兵包围.犹太士兵决定宁可自杀也不做俘虏,于是商量出了一个自杀方案.他们围成一个圈,从一个人开始,数到第 ...

  5. C++循环链表解决约瑟夫环问题

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

  6. Java数据结构之单向环形链表(解决Josephu约瑟夫环问题)

    1.Josephu(约瑟夫.约瑟夫环)问题: 设编号为1,2,… n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m 的那个人出列,它的下一位又从1开始报数,数到m ...

  7. 3,java数据结构和算法:约瑟夫环出队顺序, 单向环形链表的应用

    什么是约瑟夫环? 就是数小孩游戏: 直接上代码: 要实现这个,只需要理清思路就好了 孩子节点: class Boy{ int no;//当前孩子的编码 Boy next; // 下一节点 public ...

  8. 约瑟夫环问题详解 (c++)

    问题描述: 已知n个人(以编号0,2,3...n-1分别表示)围坐在一起.从编号为0的人开始报数,数到k的那个人出列:他的下一个人又从1开始报数,数到k的那个人又出列:依此规律重复下去,直到圆桌周围的 ...

  9. 简单约瑟夫环的循环单链表实现(C++)

    刚刚接触C++以及数据结构,今天做了第一次尝试用C++和数据结构解决问题,问题是基于约瑟夫环问题的简单版. 先来看看约瑟夫环问题的介绍: 约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3.. ...

随机推荐

  1. handlebars中的partial

    高级玩家:partial 比较推崇使用分页来实现组件化.分页跟helper一样需要先注册.在hbs模块中可以批量注册,比较简单. hbs.registerPartials(__dirname + '/ ...

  2. CentOS7 线上环境的一些 配置

    上周服务器被攻击导致上面收回了我们服务器的IP,所以这周重新安装部署了服务器,使用centos7系统.为了防止服务器再次被攻击,所以建议以下几点: 1. root密码要复杂一点,尽量字母数字特殊字符都 ...

  3. 第十五章 深入分析iBatis框架之系统架构与映射原理(待续)

    iBatis框架主要的类层次结构 iBatis框架的设计策略 iBatis框架的运行原理 iBatis框架对SQL语句的解析 数据库字段映射到Java对象 示例运行的结果 设计模式解析之简单工厂模式 ...

  4. 1106SQLserver基础--变量、运算符的使用,if...else,while语句

    数据库---变量(对数据库中的数据没有任何影响) 作用:临时存储数据的作用,起一个衔接的作用,为了方便理解存储过程. 例:Declare @hello varchar(20) Set @hello=’ ...

  5. DAY11-MYSQL索引原理与慢查询优化

    一 介绍 为何要有索引? 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,在生产环境中,我们遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,因此对查询语句 ...

  6. UML在实践中的现状和一些建议

    本文是我在csdn上看到的文章,由于认识中的共鸣,摘抄至此. 原文地址:http://blog.csdn.net/vrman/article/details/280157 UML在国内不少地方获得了应 ...

  7. 2-3 zookeeper文件夹主要目录介绍

    zookeeper-3.4.11.jar.zookeeper-3.4.11.jar.md5.zookeeper-3.4.11.sha1都是通过打包或者编译之后产生的相关的文件.那么maven相关的东西 ...

  8. Navicat MySQL安装

    1 下载安装包 点击下载安装包 2 解压安装包(解压后有三个文件) 第一个 Crack 是注册文件 第二个 chinese.rar 是汉化包 第三个 navicat_trial.exe 是安装程序 3 ...

  9. ROS Learning-019 learning_tf-03(编程) 添加额外的坐标系 (Python版)

    ROS Indigo learning_tf-03 添加额外的坐标系 (Python版) 我使用的虚拟机软件:VMware Workstation 11 使用的Ubuntu系统:Ubuntu 14.0 ...

  10. NSWindow上添加NSView

    DBSCustomView *view = [[DBSCustomView alloc] initWithFrame:NSMakeRect(100, 100, 100, 100)]; [self.wi ...