循环链表的实例——约瑟夫环

标签: 约瑟夫环 循环链表 c 数据结构 学习笔记
5人阅读 评论(0) 收藏 举报
分类:

循环链表的实例——约瑟夫环

约瑟夫环(Josephus)问题是由古罗马的历史学家约瑟夫(Josephus)提出的,该问题具体描述是:设有编号为1,2,……,n的n个人围成一个圈,从第1个人开始报数,报m(m为报数上限)的人将出列被杀掉,再从他的下一个人起重新报数,如此下去,知道所有人全部出列为止。此时,最后一个出列的将是幸存者。当任意给定n和m后,设计算法求n个人出列的次序。

由于约瑟夫环问题中要求n个人围成一圈,按照一定的方向依次报数,很自然地会想到用单循环链表来表示。下面将介绍用单循环链表解决约瑟夫环问题的有关思路。

1.数据结构

对于约瑟夫环问题,可以采用长度为n的单循环链表来表示n个人围成一圈,每当某人报数为m时,就从循环链表中将该结点删除,并从下一个结点继续开始报数。循环链表的结点中应包含一个用于存放开始时每个人在圈中排列序号(即初始循环链表中的排列位置)的id域。具体的结点结构描述如下:

typedef int ElemType;
typedef struct node{
    ElemType id;
    struct node *next;
}ListNode,*LinkList;

2.程序实现

程序中主要用到创建链表和约瑟夫环算法两个函数,具体代码如下:

#include "stdio.h"
#include "stdlib.h"
/* 常量定义 */
#define OK 0
#define Err_Momery -1
#define Err_InvalidParam -2
/* 结点结构定义*/
typedef int ElemType;
typedef struct node{
    ElemType id;
    struct node *next;
}ListNode,*LinkList;

typedef int Status;

Status CreateList(LinkList Head, int n){    // 创建具有n个结点的单循环链表
    if(!Head)
        return Err_InvalidParam;
    ListNode *p,*s;
    int i;
    Head->next = Head;      // 初始化头结点
    p = Head;               // p指向头结点Head
    for(i=1; i<=n; i++){
        s = (ListNode*)malloc(sizeof(ListNode));
        s->id = i;
        s->next = p->next;  // 将结点s插入到Head的末尾
        p->next = s;
        p = p->next;
    }
    return OK;
}

int Josephus(LinkList Head, int m){    // 约瑟夫环问题算法
    if(!Head)
        return Err_InvalidParam;
    int iCount = 1, iOrder = 0;         // 分别保存当前报数和当前出列次序
    ListNode *pcur,*pprev,*pdel;        // 分别用于指向当前结点你、前驱结点和要删除结点
    pprev = Head;
    pcur = Head->next;
    while(pprev != pcur->next){      // 当链表剩余结点大于1
        if(pcur != Head && iCount==m){  // 找到报数为m的当前结点
            pdel = pcur;                // 删除当前结点
            pprev->next = pcur->next;
            pcur = pcur->next;
            iOrder++;                   // 出列次序加1
            printf("第%d个出列序号为:%d\n", iOrder,pdel->id);
            free(pdel);
            iCount=1;                   // 重新报数,从1开始
        }
        else{
            if(pcur != Head)            // 头结点不报数
                iCount++;
            pprev = pcur;               // pprev指向当前结点
            pcur = pcur->next;          // pcur指向下一结点
        }
    }
    printf("第%d个出列序号为:%d\n", ++iOrder,Head->next->id);
    free(pcur);
    free(pprev);
    return OK;
}

int main(){
    int n,m;
    LinkList Joseph;
    printf("请输入参与人数n:");
    scanf("%d",&n);
    printf("请输入报数上限m:");
    scanf("%d",&m);
    Joseph = (ListNode*)malloc(sizeof(ListNode));
    if(CreateList(Joseph,n) != OK){
        printf("创建链表错误!\n");
        return -1;
    }
    if(Joseph->next==Joseph){
        printf("参与人数错误!\n");
        return -1;
    }
    printf("\n");
    Josephus(Joseph,m);
}
查看评论

程序员面试宝典之数据结构基础----循环链表(约瑟夫环问题)

关于循环链表,即单链表的为指针指向头结点,当然在建立循环链表的时候可以将链表的为指针指向头结点,但本例用的是先建立一个只有一个节点的循环链表(即next指针指向自己结点),然后再在此循环链表中插入节点...
  • crazyer2010
  • crazyer2010
  • 2012年10月03日 18:51
  • 4547

约瑟夫环问题(循环链表实现C)

近日复习循环链表的时候忽然想到了约瑟夫环和循环链表都有相似之处,即都为一个圆,固尝试用循环链表写一下约瑟夫环,没想到成功了。 首先先把问题描述下吧: 约瑟夫环(约瑟夫问题)是一个数学的应用问题:已...
  • I_amSHm
  • I_amSHm
  • 2016年11月21日 21:34
  • 485

数据结构练习题 约瑟夫环—用循环链表实现

#include"stdio.h" #include"stdlib.h" /*writer id: liu*/ typedef struct Node { int id; int passwo...
  • xuptacm
  • xuptacm
  • 2016年09月19日 23:24
  • 509

C语言循环链表求解约瑟夫环问题(循环方式)

/************************************************************************************************** ...
  • wuchuan53
  • wuchuan53
  • 2014年01月21日 14:22
  • 1341

用单向循环链表解决约瑟夫环(Joseph)问题

约瑟夫环(Joseph)问题的一种描述是:编号为1,2,…,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。一开始人选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始顺序报数...
  • qq_23233049
  • qq_23233049
  • 2015年04月09日 15:29
  • 5203

约瑟夫环问题循环链表实现

记录学习过程.....
  • qq1120815657
  • qq1120815657
  • 2015年03月20日 20:19
  • 387

Java循环链表实现约瑟夫环

* 单向循环链表形成约瑟环
  • chx0501
  • chx0501
  • 2015年09月27日 17:03
  • 2217

循环链表的简单应用(约瑟夫环问题场景)

题目:已知n
  • yejun556688
  • yejun556688
  • 2014年07月30日 21:08
  • 722

约瑟夫环问题(不带头结点单循环链表实现和数组实现)

Q:略         A:                   为了简化过程,类中只有3个函数即可,构造,增加,约瑟夫环解决函数    Ps:做这道题是为了巩固链表知识,在这过程中,this指...
  • ssk476079956
  • ssk476079956
  • 2012年06月13日 16:26
  • 1398

约瑟夫环 java循环链表实现

首先看一下算法背景: 罗马人攻占了乔塔帕特,41人藏在一个山洞中躲过了这场浩劫。这41个人中,包括历史学家josephus和他的一个朋友。剩余的39个人为了表示不向罗马人屈服,决定集体自杀。大家决...
  • wang_keng
  • wang_keng
  • 2017年09月01日 11:11
  • 276
    个人资料
    等级:
    访问量: 79
    积分: 71
    排名: 162万+
    文章分类
    文章存档