Josephus约瑟夫环问题循环链表实现

本文介绍了一种使用循环链表解决约瑟夫环问题的方法。通过定义循环链表类,实现了人员围坐并按特定规则出列的过程。具体包括链表的创建、遍历及删除节点等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述
已知n个人(以编号1,2,3…n分别表示)围坐在一张圆桌周围。从编号1开始报数,数到k的那个人出列;他的下一个人又从1开始报数,数到k的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。
例如n=10,k=3时,输出的出列顺序是3,6,9,2,7,1,8,5,10,4。

程序代码
CLinkList.h

#include<iostream>
using namespace std;
#define MAXSIZE 100

template<class T>
struct Node
{
    T data;     //数据域
    struct Node<T> *next;       //指针域,在这里<T>可省略
};

template<class T>
class CLinkList
{
    public:
        CLinkList(){rear = new Node<T>; rear->next = rear;} //无参构造函数
        CLinkList(T a[],int n); //有参构造函数,使用含有n个元素的数组a初始化链表
//      ~CLinkList();      //析构函数
        void PrintList();   //按次序遍历链表中的各个数据元素
        void Delete(int i);     //删除链表中第i个元素,并将该元素返回
        void Josephus(int i);
    private:
        Node<T> *rear;      //尾指针
        Node<T> *front;     //头指针
        Node<T> *p;
        int length;
};

template<class T>
CLinkList<T>::CLinkList(T a[],int n)
{
    front = new Node<T>;
    Node<T> *r = front;
    front->data = a[0];     //此构造函数中头结点也有数据,所以在出环的时候可以不用考虑头结点
    length = n;
    for(int i=1; i<n; i++)
    {
        Node<T> *s = new Node<T>;
        s->data = a[i];
        r->next = s;
        r = s;
    }
    rear = r;
    rear->next = front;
}

/*由于在josephus()函数中,已将所有元素删除,所以此处不需要析构函数
template<class T>
CLinkList<T>::~CLinkList()
{
    Node<T> *q = front;
    while(q)
    {
        front = q;
        q = q->next;
        delete front;
    }
}
*/
template<class T>
void CLinkList<T>::PrintList()
{       
    Node<T> *x = front;     
    for(int i=0; i<length; i++)
    {
        cout<<" "<<x->data<<" ";
        x = x->next;
    }
    cout<<endl;
}

template<class T>
void CLinkList<T>::Delete(int i)
{
    if(i == 0)   //如果出环间隔为0
    {
        Node<T> *q = p;
        p = q->next; 
        cout<<q->data<<" ";
        delete q;
        length--;
    }
    else    //如果出环间隔不为0
    {
        for(int x=0; x<i-2; x++)    //计算出环位置
        {   
            p=p->next;
        }
        Node<T> *q = p->next;
        p->next = q->next; 
        p = p->next;
        cout<<q->data<<" ";
        delete q;
        length--;
    }
}

template<class T>
void CLinkList<T>::Josephus(int i)
{
    p = front;
    while(length != 0)
    {
        Delete(i);
    }
}

Josephus.cpp

#include"CLinkList.h"
int main()
{
    int n,k,a[MAXSIZE];
    cout<<"请输入总数n:"<<endl;
    cin>>n;
    cout<<"请输入出环间隔k:"<<endl;
    cin>>k;
    for(int i=0; i<n; i++)
    {
        a[i]=i+1;
    }
    CLinkList<int> josephus(a,n);
//  josephus.PrintList();
    josephus.Josephus(k);
    return 0;
}

输出结果
请输入总数n:
20
请输入出环间隔k:
3
3 6 9 12 15 18 1 5 10 14 19 4 11 17 7 16 8 2 13 20
请按 ENTER 或其它命令继续

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值