循环链表之约瑟夫问题

约瑟夫问题

(上课结束,大家听说第一周没有编程题目,立刻就被鄙视了,为了纠正这个错误,咱们本周就来做点简单题目。本题要求用循环链表实现)

约瑟夫问题是一个经典的问题。已知n个人(不妨分别以编号1,2,3,…,n 代表 )围坐在一张圆桌周围,从编号为 k 的人开始,从1开始顺时针报数1, 2, 3, ...,顺时针数到m 的那个人,出列并输出。然后从出列的下一个人开始,从1开始继续顺时针报数,数到m的那个人,出列并输出,…依此重复下去,直到圆桌周围的人全部出列。

输入:n, k, m

输出:按照出列的顺序依次输出出列人的编号,编号中间相隔一个空格,每10个编号为一行。

非法输入的对应输出如下

a)

输入::n、k、m任一个小于1
输出:n,m,k must bigger than 0.

b)

输入:k>n

输出:k should not bigger than n.

例:

输入:9,3,2

输出:4 6 8 1 3 7 2 9 5

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

typedef struct node
{
    int No;
    struct node * next;
}N, *PN;

int main()
{
    int n, k, m, i, j=1;
    PN head, tmp, p, q;
    head = (PN)malloc(sizeof(N));
    head->next = NULL;
    scanf("%d",&n);
    getchar();
    scanf("%d",&k);
    getchar();
    scanf("%d",&m);

    if (n<1 || k<1 || m<1)
    {
        printf("n,m,k must bigger than 0.\n");
        return 0;
    }
    if (k>n)
    {
        printf("k should not bigger than n.\n");
        return 0;
    }
    for (i=0; i<n; i++)
    {
        tmp = (PN)malloc(sizeof(N));
        if (i==0) q = tmp;
        tmp->next = head->next;
        head->next = tmp;
        tmp->No = n-i;
        if (tmp->No == k)
            p = tmp;
    }
    q->next = head->next;
    while (n--)
    {
        for (i=1; i<m; i++)
        {
            p = p->next;
        }
        printf("%d",p->No);
        p->No = p->next->No;
        if (n == 0 || ((j++)%10==0)) printf("\n");
        else printf(" ");
        q = p->next;
        p->next = q->next;
        free(q);
    }
    free(head);
    return 0;
}
时间: 2024-10-10 18:31:17

循环链表之约瑟夫问题的相关文章

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

约瑟夫环问题可以简单的使用数组的方式实现,但是现在我使用循环链表的方法来实现,因为上午看到一道面试题规定使用循环链表解决约瑟夫环问题. 什么是约瑟夫环? “约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围.从编号为k的人开始报数,数到m的那个人出列:他的下一个人又从1开始报数,数到m的那个人又出列:依此规律重复下去,直到圆桌周围的人全部出列.”(百度百科中的解决办法列出了很多,可以看到循环链表并不是最简单的方法) 这道面试题考察了循环链表的“创建”,

(java描述)关于链表的代码-----单双、循环链表、约瑟夫环、多项式相加

将链表头尾倒置 将几个链表合并成一个新的链表,将链表中重复的节点去掉,并按大小排序 双向循环链表 单向循环链表(约瑟夫循环) 多项式相加 程序源代码 单链表.单向循环链表结点类 package javab; public class Node { int data; Node next; public Node(int data){ this.data=data; } } 第一题代码: package javab; import java.util.Scanner; public class I

循环链表解决约瑟夫问题

训练一下尾插法和循环链表的使用. //循环链表解决约瑟夫问题 #include <stdio.h> #include <stdlib.h> typedef struct CycleLinkList { int data; struct CycleLinkList * next; }cycleLinkList; cycleLinkList * h, * r, * s; // 头指针.尾指针 int main() { int i, j; int n, num; cycleLinkLis

用循环链表解决约瑟夫问题

约瑟夫问题描述:从N个人中选出一个领导人,方法如下:所有人排除一个圆圈,按顺序数数,每数到第M的人出局,此时他两边的人 靠拢重新形成圆圈,从已出局人的下一个继续进行.问题是找出哪一个人将会是最后剩下的那个人,甚至我们更希望 知道出局人的顺序. 算法思路:构造一个循环链表来表示排成圆圈的人.每人的链接指向圆圈内他左边(或者右边)的人.圆圈内人第i个人用整数i 表示.首先为1号构造一个节点的循环链表,然后再把2~N号插入到1号节点之后,得到一个1~N的环,并时x指向节点N .然后从1号开始,跳过M-

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

约瑟夫环问题 已知 n 个人(n>=1)围坐一圆桌周围,从 1 开始顺序编号,从序号为 1 的人开始报数,顺时针数到 m 的那个人出列.下一个人又从 1 开始报数,数到m 的那个人又出列.依此规则重复下去,直到所有人全部出列.请问最后一个出列的人的初始编号. 要求 输入人数 n,所报数 m,输出最后一个人的初始编号. 解决思路 首先因为是圆桌问题,使用链表解决的话需要构建循环链表. 接着是出列问题,这里我的设计思路是将指向链表的指针移动到需要出列的人的位置,然后根据正常的链表删除进行操作即可.

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

1.问题 2.代码实现 /** * 使用循环链表实现解决约瑟夫环问题 * */ //链表节点 function Node(element){ this.element = element; this.next = null; } //定义链表类 function LList(){ this.head = new Node("head"); this.head.next = this.head; this.find = find; this.insert = insert; this.f

用循环链表求解约瑟夫问题

约瑟夫问题的提法:n个人围成一个圆圈,首先第1个人从1开始,一个人一个人的顺时针报数,报到第m个人,令其出列:然后再从下一个人开始,从1顺时针报数,报到第m个人,再令其出列,…,如此下去,直到圆圈中只剩一个人为止,此人即为优胜者. 例如  n = 8   m = 3 该问题老师让我们在带头节点的单循环链表,不带头节点的单循环链表,双向循环链表,静态循环链表中四选其一实现,我看到问题后第一反应选了带头节点单循环链表,以为这样可以统一空表和非空表的操作,事实上在这个问题中并不需要考虑这些,不过好在四

循环链表,约瑟夫环问题

约瑟夫(Josephus)环问题:编号为1,2,3,…,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数).一开始任选一个正整数作为报数的上限值m,从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止.报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一人开始重新从1报数,如此下去,直到所有人全部出列为止. 建立n个人的单循环链表存储结构,运行结束后,输出依次出队的人的序号. #include <stdio.h>#include <stdlib.h>#incl

单向循环链表(约瑟夫环)

#include<stdio.h> #include<stdlib.h> #define N 10 typedef struct node{ int  data; struct node * next; }ElemSN; ElemSN*Createlink(int a[],int n){ int i; ElemSN*h=NULL,*p,*t; for(i=0;i<N;i++){ p=(ElemSN*)malloc(sizeof(ElemSN)); p->data=a[i