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

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

图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. 关联,聚合和组合(复合)--Association, Aggregation and Composition

    概要 Association, Aggregation and Composition are terms that represent relationships among objects. Th ...

  2. C Primer Plus学习笔记(七)- 字符输入/输出和输入验证

    单字符 I/O:getchar() 和 putchar() getchar() 和 putchar() 每次只处理一个字符 getchar() 和 putchar() 都不是真正的函数,它们被定义为供 ...

  3. python 函数对象、函数嵌套、名称空间与作用域、装饰器

    一 函数对象 一 函数是第一类对象,即函数可以当作数据传递 1 可以被引用 2 可以当作参数传递 3 返回值可以是函数 3 可以当作容器类型的元素 二 利用该特性,优雅的取代多分支的if def fo ...

  4. Shell编程进阶 1.2 shell结构及执行

    创建一个shell脚本 mkdir shell vim first.sh #!/bin/bash ##The first test shell script. ##Written by wangsha ...

  5. 使用ffmpeg合并视频

    命令: ffmpeg -i concat:"1.avi|2.avi" -vcodec copy -acodec copy "3.avi" ffmpeg下载:ht ...

  6. 使用Post进行Http通信

    --------------siwuxie095                             有道翻译官网:http://fanyi.youdao.com/     找到官网页面下方的 有 ...

  7. OpenGL超级宝典完整源码(第五版)

    链接:https://pan.baidu.com/s/1dGQkk4T 密码:wu44 Visual Studio 2017配置OpenGL https://blog.csdn.net/qiangbi ...

  8. 已看1.熟练的使用Java语言进行面向对象程序设计,有良好的编程习惯,熟悉常用的Java API,包括集合框架、多线程(并发编程)、I/O(NIO)、Socket、JDBC、XML、反射等。[泛型]\

    1.熟练的使用Java语言进行面向对象程序设计,有良好的编程习惯,熟悉常用的Java API,包括集合框架.多线程(并发编程).I/O(NIO).Socket.JDBC.XML.反射等.[泛型]\1* ...

  9. 利用General框架开发RDLC报表

    RDLC是微软推出的自家的报表软件,虽然没有一些第三方的报表软件强大好用,但是作为VisualStudio集成的报表工具,在客户要求不高的情况下还是非常值得一用的,本文将介绍通过General代码生成 ...

  10. input框去只读

    设置为只读 $('input[name=video_link]').attr("readonly","readonly"); 去只读 $("#vide ...