C++ || 数据结构--约瑟夫(Josephu)问题

约瑟夫(Josephu)问题:已知n个人(以编号1,2,3,…,代表)围坐成一圈。现在从编号为k的人开始报数,数到m的人出列;他的下一个人又从1开始报数,数到m的人又出列;依此重复下去,直到所有人全部出列。例如:当n=8,m=4,k=3 时,出列顺序为 6,2,7,4,3,5,1,8。

 

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;

typedef struct node
{
    int data;
    struct node *next;
}Node,*Link;

//创建一个带有头节点的循环链表,控制从 k 开始计数 
Link create(int n,int k)
{
    Link head = NULL,p = NULL, pr = NULL;   //pr是一个新节点 p前一个节点
    int i;
    for(i = 1;i <= n;i++)
    {
        p = (Link)malloc(sizeof(Node));
        if(p == NULL)
        {
            cout << " 动态内存分配失败 ";
            return NULL; 
        }
        p->data = i; 
        if(head == NULL)    //如果头节点指针为空 ,直接释放  
        {
            head = p;
        }
        else
        {
            pr->next = p;   
        }
        pr = p; 
    } 
    p->next = head;         //循环结束,回到头节点,形成一个完整的循环链表
    p = head;
    
    //从第一个人开始计数 
    for(i = 1;i < k;i++)
    {
        pr = p;
        p = p->next;        //k个跳出循环  
    } 
    return p;               //返回指定的第一个人      
} 

//传入链表并定义数字 
void Josephus(Link p,int m)
{
    Link pr = NULL;
    int i;
    cout << "出列顺序:\n";
    while(p->next != p)     //循环链表的首尾不相连 
    {
        for(i = 1;i < m;i++)
        {
            pr = p;
            p = p->next;    
        }                       //循环结束,出列
        pr->next = p->next; 
        cout << p->data <<"\n"; //输出出列人顺序 
        free(p); // 释放  
        p = pr->next;   //重新指向 新开始节点 
    }  
    cout << p->data;
    return; 
} 

int main()
{
    Link p = NULL;
    int n,k,m;
    cout << "总人数:";cin >> n;//输入总人数 
    if(n<=0){
        cout << "请输入正确人数,总人数应为大于0的正整数!\n"; 
    }
    else{
    cout << "出列数:";cin >> m;        //出列数
    cout << "开始编号:";cin>> k;        //开始计数
    p = create(n,k);
    Josephus(p,m); 
    }
    return 0;
}

验证:

输入:8,4,3

输出顺序: 6,2,7,4,3,5,1,8

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是使用单向循环链表实现约瑟夫问题C++代码: ``` #include <iostream> using namespace std; // 定义单向循环链表结点结构体 struct ListNode { int val; ListNode* next; ListNode(int x) : val(x), next(nullptr) {} }; // 约瑟夫问题求解函数 void josephu(int n, int m) { // 构造循环链表 ListNode* head = new ListNode(1); ListNode* p = head; for (int i = 2; i <= n; i++) { p->next = new ListNode(i); p = p->next; } p->next = head; // 将链表尾部连接到头部,形成循环链表 // 模拟约瑟夫问题的求解过程 p = head; while (p->next != p) { // 当链表中只剩一个结点时停止 for (int i = 1; i < m; i++) { p = p->next; // 找到要删除的结点的前一个结点 } ListNode* del = p->next; // 要删除的结点 p->next = del->next; // 将要删除的结点从链表中删除 cout << del->val << " "; // 输出删除的结点的值 delete del; // 释放被删除结点的内存空间 } cout << p->val << endl; // 输出最后剩下的结点的值 delete p; // 释放最后剩下的结点的内存空间 } int main() { int n, m; cout << "请输入总人数n和报数m:"; cin >> n >> m; josephu(n, m); return 0; } ``` 在上述代码中,我们首先构造了一个包含1~n的单向循环链表,然后模拟了约瑟夫问题的求解过程。具体来说,我们用一个指针p来遍历链表,每次找到要删除的结点的前一个结点,并将要删除的结点从链表中删除,并输出其值。当链表中只剩一个结点时,即p->next==p时,算法结束,输出最后剩下的结点的值。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小嘤嘤怪学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值