数据结构 约瑟夫环问题

实验一  线性表的应用

实验目的和要求:

通过实验进一步理解线性表的逻辑结构和存储结构,提高使用理论知识指导解决实际问题的能力,熟练掌握链表的实际应用。

主要内容:

题目Josephus环问题

问题描述:

约瑟夫(Joseph)问题的一种描述是:编号为1,2,…,nn个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止报数。报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直到所有人全部出列为止。试设计一个程序求出出列顺序。

基本要求:

利用单向循环链表存储结构模拟此过程,按照出列的顺序印出各人的编号。

测试数据:

m的初值为20;n=7,7个人的密码依次为:3,1,7,2,4,8,4,首先m值为6(正确的出列顺序应为6,1,4,7,2,3,5)。

1.建链表按书上写,不带头节点的循环链表

2.遍历  删除找前驱,更新M 值,data域

M=20,或6,序号,data域多一项

 


// 约瑟夫环问题.cpp : 定义控制台应用程序的入口点。

//

#include "stdafx.h"
#include<iostream>
using namespace std;
typedef struct Node{
    int number,password;
    struct Node *next;
}LNode,*LinkList;
LinkList Creat_LinkList1(int n){    //建从尾部插入链表
    LinkList L;
    LNode *s, *r;
    int num, m;//num为序号, m为密码
    L = r = NULL;    
    num = 1;
    while (num < n+1){
        s = new LNode;
    
        cout << "请输入第"<<num<<"个人的m值:"<<"\t" ;
        cin >> m;
        int p;
        p=num++;
        s->number =p;//序号
        s->password = m; //m密码值
        if (L == NULL)
            L = s;//对第一个节点的处理
        else
            r->next = s;
        r = s;//对其他节点的处理
    }
    if (r != NULL)
        r->next = L;  //最后一个元素指向头结点
    return L;
}

void Joseph(LinkList L, int m)
{
    LNode *p, *s, *r;
    p = L;
    int n1 = 1, num;
    cout<<"正确的出列顺序为:"<<endl;
    while (p->next!= p){
            for (int i=1; i<m-1; i++)
                p=p->next;//找前驱
            s=p->next;
            p->next = s->next;
            m=s->password;//保存m值
            cout<<s->number<<'\t';
            delete s;//删除节点
            n1++;
            if (m!=1)//当m等于1时,则下一个出列的人为报1的人,则p不变,当m不等于1时,则需将p指向p->next
            p = p->next;        
    }
        cout <<p->number<<endl;;
}
int _tmain(int argc, _TCHAR* argv[]){
    int m,n;
    Node *L;
    L=NULL;
    cout << "请输入m的初始值:";
    cin >>m;
    LinkList L1;
    cout<<"请输入总人数n:";
    cin>>n;
    L1 = Creat_LinkList1(n);
    Joseph(L1,m);
   return 0;
}

  • 6
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
题目: 每个人手里有个密码。开始给定一个正数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) 释放结点模块;

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值