数据结构 -- 约瑟夫环

这是数据结构的实验~~

这是求解经典的约瑟夫环的算法实现。

这里是采用循环单链表实现的。

所以程序可读性不错。

 

有朋友发现了这个问题,注释里说退席的顺序是错的,我是直接把老师给的题目粘上去的

后来我试验过也发现是错的,但忘了修改了。呵呵

正确的序列的确是6, 1, 7, 5, 3, 2, 4(感谢大家指错)

程序本身没有错误。

 

Experiment1_2.h 包括了算法的几个基本的函数。

/* Experiment1_2.h */

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// 实验题1.2  问题描述:
// 编号为1,2,···,n的n个人围坐在一圆桌旁,每人持有一个正整数的密码。
// 从第一个人开始报数,报到一个预先约定的正整数m时,停止报数,报m的人退席,
// 下一个人又重新从1开始报数,依此重复,直至所有的人都退席。
// 编一程序输出他们退席的编号序列。
// 例如,设m=20,n=7,7个人的密码依次是3,1,7,2,4,8,4,
// 则退席的人的编号依次为6,1,4,7,2,3,5。
//
// 提示2:
// 用不带表头结点的循环单链表表示围成圆圈的n个人;
// 建立此循环单链表;
// 某人离席相当于删除一个结点要正确设置程序中循环终止的条件和删除结点时指针的修改变化。
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

#include <iostream>
using namespace std;

// - - - - - - 基本常量 - - - - - - 
#define OK 1    // 成功
#define FAIL 0  // 失败


// - - - - - - 数据结构 - - - - - - 

// 约瑟夫环的元素类型,number为编号,code为密码
typedef struct
{
    int number;
    int code;
}People, ElemType;

// 没有头结点的循环链表结点类型,cLinkList代表循环链表, LNode代表结点
typedef struct cLinkList
{
    People people;
    struct cLinkList* next;
}cLinkList, LNode;

// - - - - - - 基本函数 - - - - - - 

// 创建约瑟夫环
int CreateJosephus(cLinkList*& cl, const int m);

// 输出约瑟夫环的退席结果
int Josephus(cLinkList*& cl, const int m, const int n);


int CreateJosephus(cLinkList*& cl, const int m)
{
    cl = new cLinkList;
    // 创建m人的约瑟夫环
    if (m <= 0) {
        cl = NULL;
        return FAIL;
    }

    LNode* p;
    LNode* q;

    p = cl;

    cout << "/ - 输入各密码:";
    p->people.number = 1;
    cin >> p->people.code;

    int i;
    for (i = 2; i <= m; i++) {
        q = new LNode;
        q->people.number = i;
        cin >> q->people.code;

        p->next = q;
        p = p->next;
    }
    p->next = cl;
}


int Josephus(cLinkList*& cl, const int m, const int n)
{
    // 输出约瑟夫环的退席结果,m为报数值,n为人数
    if (!cl || m <= 0 || n <= 0) {
        return FAIL;
    }

    // 循环变量
    int i;
    int j;

    // leave指针指向要退席的位置
    LNode* p;
    LNode* leave;

    // 预处理p指针,指向循环链表的表尾
    p = cl;
    for (i = 1; i < n; i++) {
        p = p->next;
    }

    // 输出约瑟夫退席结果
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m - 1; j++) {
            p = p->next;
        }
        leave = p->next;
        cout << leave->people.number << "(" << leave->people.code << ") ";
        p->next = leave->next;
        delete leave;
    }

    return OK;
}

test.cpp 应用算法求解约瑟夫环。

/* test.cpp */

#include "Experiment1_2.h"

#include <iostream>
using namespace std;

int main()
{
    cLinkList* cl;

    int n;
    int m;

    cout << "/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - " << endl;
    cout << "/ -                 实验题1.2 约瑟夫环问题" << endl;
    cout << "/ - " << endl;
    cout << "/ -  注:人数和报数值都为大于等于1的正整数" << endl;
    cout << "/ -  注:密码为整数" << endl;
    cout << "/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - " << endl;

    cout << "/ - 人数:";
    cin >> n;
    cout << endl;
    CreateJosephus(cl, n);
    cout << endl;

    cout << "/ - 报数值:";
    cin >> m;
    cout << endl;

    cout << "/ - 出席序列为:";
    Josephus(cl, m, n);
    cout << endl;

    return 0;
}

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值