【循环链表】约瑟夫死亡游戏

前言:循环链表时一种头尾相接的链表。其特点是无须增加存储量,仅对表的链接方式稍作改变,即可使得表处理更加方便灵活。

如何构成循环单链表?

在单链表中,将终端结点的指针域NULL改为指向表头结点的或开始结点,就得到了单链形式的循环链表,并简单称为单循环链表。

为什么用尾指针表示循环单链表?

在很多实际问题中,表的操作常常是在表的首尾位置上进行,此时头指针表示的单循环链表就显得不够方便.如果改用尾指针rear来表示单循环链表,则查找开始结点a1和终端结点an都很方便,它们的存储位置分别是(rear–>next) —>nextrear,显然,查找时间都是O(1)。因此,实际中多采用尾指针表示单循环链表。

下面是一个循环单链表的例子:

/*
                          copyright(c)2012 三江学院 电子信息工程
* 文件名称:josephus.c
* 文件标识:见配置管理计划书
* 摘要:约瑟夫问题,共有N个犹太人,包括约瑟夫和他的朋友,这N个人决定自杀,
但是约瑟夫和他朋友都不想死,于是他们设计了一个死亡游戏 ,最终他俩免于一死。
游戏规则:N个人围成一圈,然后从某个人开始数数(此人算作第一个),第M个人自
杀,有一个人死后,从他下一个人开始数数。
* 当前版本:1.1
* 作者:黄路
* 完成日期:2012年7月1日

*/
#include <stdio.h>
#include <stdlib.h>

typedef struct Jew
{
     int number;
     struct Jew *next;
}Jew;

int main(int argc, char *argv[])
{
     Jew *jew;//指向链表头
     Jew *r;  //指向当前节点
     int N;   //总人数
     int M;   //自杀间距
     int i;

     printf("input number of jew(N) and interval(M):\n");
     scanf("%d, %d", &N, &M);

     jew = (Jew*)malloc(N * sizeof(Jew)); //为链表分配内存
     //      memory check
     if ( NULL== jew)
     {
          printf(" no memory!\n");
          return 0;
     }

     r = jew;
     //init list
     for (i = 1; i < N; i++)
     {
          r->number = i;
          r->next = jew + i; //在连续内存中操作
          r = r->next;
     }
     r->number = N;
     r->next = jew;//形成单循环链表

     printf("suicide order:\n");
     while (r != r->next)
     {
          //实现跳跃式杀人,第M个自杀
          for (i = 1; i < M; i++)
          {
               r = r->next;
          }
          printf("%4d\n", r->next->number);
          r->next = r->next->next; //被杀的人从链表上消失!!
     }

     printf("\n when N = %d and M = %d\nJosephus, hiding in position %d survives.\n", N, M, r->number);
     free(jew);

     return 0;
}

 

    原文作者:约瑟夫环问题
    原文地址: https://blog.csdn.net/to_dreams/article/details/7706150
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞