随机密码约瑟夫环

问题:

约瑟夫环问题:

问题描述:设有编号为1,2,3……n的n个人顺时针方向围坐一圈,每人有一密码(正整数)。开始时给出一初始密码m,从编号为1的人开始报数,报m的人出列;以后将出列者的密码作为新的m,从顺时针方向紧挨着他的下一个人开始报数……直至所有人出列。试编算法,求出出列顺序。

要求:

  1. 用不带头结点的单向循环链表实现
  2. 从键盘输入n,m
  3. 各人的密码由计算机随机产生(1~10的正整数,也可以自己指定)
//使用循环链表来解决约瑟夫环问题
//需要对链表实现的功能:
//1. 初始化链表节点值
//2. 删掉对应元素
//3. 返回对应值和序号

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

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2

typedef int Status;

typedef struct LinkNode{
    int number;// 序号
    struct LinkNode* next;// 指向下一个节点的指针
}LinkNode, *LinkList;// 指向结构体的指针

// 设立尾指针的单循环链表
Status ListInit_CL(LinkList &L, int given_people)
{
    LinkList l = (LinkList)malloc(sizeof(struct LinkNode));
    if (!l)
        exit(OVERFLOW);

    L = l;// L就当作首,方便最后传出时,L没有变化

    int index;
    for (index = 0; index < given_people - 1; index++)// 循环赋值
    {
        l->number = index + 1;

        LinkList q = (LinkList)malloc(sizeof(struct LinkNode));// 临时存储
        if (!q) // 分配失败
            return OVERFLOW;

        l->next = q;
        l = q;// 移位,当在最后一次的循环中,l所在是空的
        q = NULL;
        free(q);
    }

    l->number = index + 1;
    l->next = L;

    return OK;
}

// 删除第i个元素,并由number返回其序号
Status ListDelete_CL(LinkList &L, int i, int &number)
{
    LinkList q;
    int j;

    if (i > 1)
    {
        for (j = 0; j < i - 1; j++)// 移动i-1次,寻找后面第i-1个结点
            L = L->next;

        q = L->next;// q指向待删除结点
        L->next = q->next;// L->next指向被删除节点的下一个
    }
    else if (i == 1)
    {
        q = L;//q指向第一个有效位
        for (j = 0;; j++)// 移动到最后面,使最后指向第二个有效位,并移动过去
        {
            L = L->next;
            if (L->next == q)
            {
                L->next = q->next;
                break;
            }
        }
    }
    else
    {
        return ERROR;
    }

    //返回被删除节点序号
    number = q->number;

    free(q);
    return OK;
}

int main()
{
    int i, first_num, get_number, given_people, given_maxnum;
    printf("请输入:初始人数n,初始密码m\n");
    scanf("%d %d", &given_people, &first_num);
    if (given_people <= 0 || first_num <= 0)
        return ERROR;

    LinkList L = NULL;
    if (!ListInit_CL(L, given_people))
        return ERROR;

    given_maxnum = first_num == 1 ? 1 : (first_num - 1);
    ListDelete_CL(L, given_maxnum, get_number);
    printf("随机数-->%d,被剔除-->%d\n", first_num, get_number);

    int index;
    int rand_number;
    srand((unsigned)time(NULL));
    for (index = 0; index < given_people - 2; index++)// 只删除n-2个,除了前面删除的一个,最后剩下的就是没有删除的。
    {
        ListDelete_CL(L, rand_number = rand() % 10 + 1, get_number);
        printf("随机数-->%d,被剔除-->%d\n", rand_number, get_number);
    }
    printf("被剩下-->%d\n", L->number);

    return OK;
}
题目: 每个人手里有个密码。开始给定一个正数m,做为报数上限,从某个人开始循环报数,报到m的人出列;再以该出列的人手中的密码为报数上限,依次报数。打印出列的人的序号的先后顺序。 一. 需求分析 1. 本演示程序中,人数n应为任意的,首先应输入一个赋给初始报数上限m,程序应能自动保存出列人的序号和将出列的人所持的密码赋给m,再次作为报数上限,如此循环,直至所有人都出列为止。 2. 演示程序以用户和计算机的对话方式执行,即在计算机终端上显示“提示信息”之后,由用户在键盘上输入相应数据(即每个人所持的密码),每个人的序号由程序自动分配。 3. 程序执行的命令包括: (1)构造链表;(2)输入数据;(3)执行报数,储存出列人的序号,删除出列人的信息以及把出列人的密码赋给m;(4)结束。 4. 测试数据 (1)m=20,n=7,7个人密码依次为:3,1,7,2,4,8,4,首先m为6,则这正确的出列顺序为6,1,4,7,2,3,5。 确的出列顺序为6,1,4,7,2,3,5。 二. 概要设计 为了实现上述操作,应以单向循环链表为存储结构。 1. 基本操作: code( ) 操作结果:构造空链表,若成功就初始化每个人的相关信息 code( ) 初始条件:线性链表存在 操作结果:释放指向出列的人的结点,并重新报数 2. 本程序包含三个模块: (1) 主程序模块; (2) 构造链表并输入每个人信息模块; (3) 释放结点模块;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值