您当前的位置: 首页 >  数据结构
  • 1浏览

    0关注

    880博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

【大话数据结构C语言】8 循环链表

CodeAllen嵌入式编程 发布时间:2020-10-13 23:09:56 ,浏览量:1

系列文章参考资料为《大话数据结构》,源码为个人私有,未经允许不得转载 技术交流群或资料添加微信号:CoderAllen,回复关键字即可

将单链表中终端结点的指针端由空指针改为指向头结点,就使整个单链表形成一个环,这种头尾详解的单链表就是单循环链表,简称循环链表(circular linkedlist)

循环链表解决了一个单链表中很麻烦的问题 - 如何从当中一个结点出发,访问到链表的全部结点

循环链表带有头结点的空链表: 加粗样式在这里插入图片描述

循环链表的非空链表: 在这里插入图片描述

其实循环链表和单链表的主要差异就在于循环的判断条件上 - 由判断p->next是否为空,改为p->next不等于头结点,否则循环结束

练习:循环链表实现约瑟夫环 约瑟夫环问题,是一个经典的循环链表问题,题意是:已知 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 胜出

约瑟夫环问题有多种变形,比如顺时针转改为逆时针等,虽然问题的细节有多>种变数,但解决问题的中心思想是一样的,即使用循环链表。

编译平台为VS2019

#include 
#include 
typedef struct node{
    int number;
    struct node * next;
}person;
person * initLink(int n){
    person * head=(person*)malloc(sizeof(person));
    head->number=1;
    head->next=NULL;
    person * cyclic=head;
    for (int i=2; inumber=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=1; inext;
        }
        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_s("%d",&n);
    person * head=initLink(n);
    printf("从第k人开始报数(k>1且k            
关注
打赏
1665938897
查看更多评论
0.0403s