【转】约瑟夫环算法---------题目:有n个人围成一圈,顺序排号,从第一个开始报数(从1到3报数),凡报到3的人退出圈子,问最后最后留下的是原来第几号的那位.

提示:用环形链表实现

对于这个题目其实就是用c语言的循环链表实现一个约瑟夫环。我们可以定义一个循环链表,将这n个人加入到链表中,然后定义三个节点指针在链表上循环,移动跨度为3,利用链表的循环功能每次删除第三个节点,这边要注意的一个问题就是你定义的是3个指针,且在循环中他们彼此也都是有

->next关系,一般我们判断循环结束条件时都是一个节点的下一个节点是否为它本身(如ptr->next == ptr),这里我们要注意循环体中链接方向否则很可能出现无用指针导致错误,因为最后我们要剩下一个节点那么ptr->next为NULL,而剩下的不能是NULL->next.

具体程序,如下:

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

struct node
{
    int num;
    struct node *next;
};

struct node *head;
struct node *last;

void cre_list()
{
    head = (struct node *)malloc(sizeof(struct node));
    last = head;
    head->next = head;
}

void display_node()
{
    struct node *ptr = head->next;
    while(ptr != head)
    {
        printf("%d\t",ptr->num);
        ptr = ptr->next;
    }
    printf("\n");
}

void add_node(int num)
{
    struct node *ptr = (struct node *)malloc(sizeof(struct node));
    ptr->num = num;
    ptr->next = head;
    last->next = ptr;
    last = ptr;
}

void rev_node()
{
    struct node *ptr = head;
    last->next = head->next;
    head = head->next;
    free(ptr);
}

void tiren_node()
{
    struct node *ptr = head;
    struct node *str = ptr->next;
    struct node *qtr = str->next;
    while(ptr->next != ptr)
    {
        str = ptr->next;
        qtr = str->next;
        str->next = qtr->next;
        ptr = str->next;
    }
    printf("%d\n",ptr->num);
}

int main()
{
    int i = 0;
    cre_list();
    int n;
    printf("please input n:\n");
    scanf("%d",&n);
    printf("%d\n",n);
    for(i = 1;i <= n;i++)
    {
        add_node(i);
    }
    display_node();
    rev_node();
    tiren_node();
    return 0;
}

时间: 2024-10-19 23:40:29

【转】约瑟夫环算法---------题目:有n个人围成一圈,顺序排号,从第一个开始报数(从1到3报数),凡报到3的人退出圈子,问最后最后留下的是原来第几号的那位.的相关文章

java例题_37 有 n 个人围成一圈,顺序排号。从第一个人开始报数(从 1 到 3 报数),凡报到 3 的人退出圈子, 3 问最后留下的是原来第几号的那位。

1 /*37 [程序 37 报数] 2 题目:有 n 个人围成一圈,顺序排号.从第一个人开始报数(从 1 到 3 报数),凡报到 3 的人退出圈子, 3 问最后留下的是原来第几号的那位. 4 */ 5 6 /*分析1====错误分析,没有注意到要退出圈子!!! 7 * 1.用一个数组存放n个1,从头开始报数 8 * 2.声明一个计数器,报数为3时,数组中的数赋为0,计数器重置 9 * 3.一直直到还剩下最后一个不为0的数,这个数的角标加1就是原来的几号 10 * 11 * 分析2:----利用A

10.5 有n人围成一圈,顺序排号。从第1个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来的第几号的那位。

有n人围成一圈,顺序排号.从第1个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来的第几号的那位. #include <stdio.h> int main(){ int num[50]; int * p,n,i; p=num; printf("输入人的数目n="); scanf("%d",&n); //为每人赋初始的序号 for(i=0; i<n; i++){ *(p+i)=i+1; } int m=0,j=0,k=0;

5、题目:有n个人围成一圈,顺序排号。从第一个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来第几号的那位。 思路:n长度的数组,boolean类型。出圈置为false,当最后只有一个true的时候,就是留下来的人。

public class Test { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("请输入人的个数n:"); int n = sc.nextInt(); fun(n); sc.close(); } private static void fun(int n) { boolean[] ps = new boolean[n]; int co

有n人围成一圈,顺序排号。从第1个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来的第几号的那位。

#include <iostream> using namespace std; int main() { int i,j,n,m,k,*p,num[100];k=m=0;   cin>>n;      p=num;      for(i=0;i<n;i++)          *(p+i)=i+1;      i=0;      while(m<n-1)      { if(*(p+i)!=0)            k++;         if(k==3)    

有17个人围成一圈,顺序排号。从第一个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下&#160;的是原来第几号的那位

int n = 17;  boolean[] persons = new boolean[n];  //初始化  for(int i=0;i<persons.length;i++){   persons[i] = true;  }    int len = persons.length;//剩下的人数  int count = 0;  while(len>1){   //继续报数   for(int i=0;i<persons.length;i++){    if(persons[i])

用Matlab完成:从第一个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来第几号的那位。

程序思路: (1)一圈人循环报数,报数报到3的人,将其置为0,表示被淘汰: (2)那么在接下去的循环中,被淘汰的人不参与报数: (3)直到仅有1人没被淘汰,并显示出他之前的编号. 程序实现如下: clear all n=input('Please input the number:') A=zeros(1,n) for i=1:n                                                         %对每个人进行顺序编号     A(i)=iend o

约瑟夫环算法

首先阐述一下问题:n个人(编号0—n-1)围成一圈,从1开始报数,报到m的人出列,然后从出列的人的下一个人开始,从1开始报数,报到m的人出列,求出最后幸存的那个人的原始编号. 如果单纯的是模拟整个游戏过程的话,实现起来并不难.今天我学习到的是另一种算法.举个例子,第一轮以后,假设被淘汰的人编号是k-1,报数是m,那么接下来的n-1的应该是这样排序x`(x),x`表示上一轮的编号,x表示本轮的编号.那么目前的情况应该是这样的k(0).k+1(1).k+2(2).…….k-2(n-2),我们可以得出

关于约瑟夫环算法,数组解决

据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止.然而Josephus 和他的朋友并不想遵从.首先从一个人开始,越过k-2个人(因为第一个人已经被越过),并杀掉第k个人.接着,再越过k-1个人,并杀掉第k个人.这个过程沿着圆圈一直

java常见算法题目

1: JAVA经典算法40题 2: [程序1] 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第四个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 3: 1.程序分析: 兔子的规律为数列1,1,2,3,5,8,13,21.... 4: public class exp2{ 5: public static void main(String args[]){ 6: int i=0; 7: for(i=1;i<=20;i++) 8: System.o