PTA练习之约瑟夫问题

6 篇文章 1 订阅
2 篇文章 0 订阅

Josephus

问题描述:编号为1,2,…,n的n个人按顺时针方向围坐在一张圆桌周围,每人持有一个密码(正整数)。一开始任选一个正整数m作为报数上限值,从第一个人开始按顺时针方向自1开始报数,报到m时停止报数,报m的那个人出列,将他的密码作为新的m值,从他顺时针方向的下一个人开始重新从1报数,数到m的那个人又出列;如此下去,直至圆桌周围的人全部出列为止。要求按出列顺序输出n个人的编号。

输入格式:
第一行输入两个整数,依次表示人数n和初始化密码m,以空格间隔。 第二行依次输入n个整数,分别表示n个人的密码,以空格间隔。

输出格式:
按出列次序输出每个人的编号,以空格间隔。

输入样例:
在这里给出一组输入。例如:
7 20
3 1 7 2 4 8 4

输出样例:
在这里给出相应的输出。例如:
6 1 4 7 2 3 5

/思路:循环链表,循环移动结点,找到后删除结点,继续寻找,直至所有结点都被找过/

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

typedef struct node
{
    int num, password;
    struct node *next;
}*Linklist;
Linklist H,r,s;
//创建循环链表
void Creat_Tlinklist(int n)
{
    H = (Linklist)malloc(sizeof(Linklist));
	r = H;
    int i;
    int x;
    for (i = 1; i < n;i++)
    {
        s = (Linklist)malloc(sizeof(Linklist));
        r->next = s;
        r = s;
    }
    r->next = H;
    s = H;
}

void input_Linklist(int n)
{
	int x;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&x);
		s->password = x;
		s->num = i;
		s=s->next;
	}
	s = r;
}
//输出并出列
void Output_Linklist(int n,int m)
{
    for (int i = 1; i <= n;i++)
    {
        for (int j = 1; j <m;j++)
            s = s->next;//找到结点
        r = s->next;
        m = r->password;
        printf("%d ", r->num);
        s->next = r->next;
        free(r);
    }
}

//主函数
int main()
{
    int n, m;
    scanf("%d %d", &n, &m);
    Creat_Tlinklist(n);
    input_Linklist(n);
    Output_Linklist(n, m);
    return 0;
}

问题二
编号为1,2,…,n的n个人按顺时针方向围坐在一张圆桌周围。给定一个正整数m≤n,从第一个人开始按顺时针方向自1开始报数,每报到m时就让其出列,从 他顺时针方向的下一个人开始重新从1报数,数到m的那个人又出列。如此下去,直至圆桌周围的人全部出列为止。每个人的出列次序定义了整数1,2,3,…,n的一个排列。这个 排列称为一个(n,m)Josephus排列。例如:(7,3)Josephus排列为3,6,2,7,5,1,4。

输入格式:
输入两个整数,人数n和密码m,以空格间隔。

输出格式:
按出列次序输出每个人的编号,以空格间隔。

输入样例:
在这里给出一组输入。例如:
7 3

输出样例:
在这里给出相应的输出。例如:
3 6 2 7 5 1 4
/思路:和上题一样不过这次不需要提供密码,也就是循环一致,其实我们把上题中所有有关密码的操作全部去掉就可以了/

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

typedef struct node
{
    int num;
    struct node *next;
}*Linklist;
Linklist H,r,s;
//创建循环链表
void Creat_Tlinklist(int n)
{
    H = (Linklist)malloc(sizeof(Linklist));
	r = H;
    int i;
    for (i = 1; i < n;i++)
    {
        s = (Linklist)malloc(sizeof(Linklist));
        r->next = s;
        r = s;
    }
    r->next = H;
    s = H;
}

void input_Linklist(int n)
{
	for(int i=1;i<=n;i++)
	{
		s->num = i;
		s=s->next;
	}
	s = r;
}
//输出并出列
void Output_Linklist(int n,int m)
{
    for (int i = 1; i <= n;i++)
    {
        for (int j = 1; j <m;j++)
            s = s->next;//找到第i-1个结点
        r = s->next;
        printf("%d ", r->num);
        s->next = r->next;
        free(r);
    }
}

//主函数
int main()
{
    int n, m;
    scanf("%d %d", &n, &m);
    Creat_Tlinklist(n);
    input_Linklist(n);
    Output_Linklist(n, m);
    return 0;
}

以上代码仅供参考,有问题希望大佬指正!!!

  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值