Josephus问题求解

Josephus问题是一个基于数据结构中链表运用的一个实例,通过目前的主流程序设计语言(C C++ Java)均可进行算法的演示。本人作为大二的电信程序小白一枚,曾花了将近2天的时间去完成老师布置的C++实现方法,希望本程序菜鸟的经验分享可以为广大小白提供些许帮助:)

百度百科上给出的Josephus问题的历史原型是这样的:
在罗马人占领乔塔帕特後,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。
(https://baike.baidu.com/item/Josephus/22032698)

而问题需要实现的,就是依次打印出自杀人的编号顺序和最后幸存者的编号。

本人已经用C++代码实现,其源代码为:

//Josephus问题求解 
#include <iostream>
#include <cstdlib>
using namespace std;

//A node in the list
class node
{
public:
    int data;     //data is the an element number
    node *next;
};

//尾插法链表的建立 
node* List_create()
{
    int total;
    cin>>total;
    node *p1,*p2,*head;
    p1=p2=head=new node;
    for(int i=total;;i--)
    {
        p2->data=i;
        if(i==1){break;}
        p1=new node;
        p1->next=p2;
        p2=p1;
    }
    head->next=p1;
    return head;
}

//尾插法链表的遍历 
void traverse(node *head)
{
    node *p=head->next;
    while(1)
    {
        cout<<p->data<<" ";
        if(p==head){break;}
        p=p->next;
    }
}

node *List_delete(int i,node *head)
{
    node *p1=head->next,*p2;
    while(p1->next->data!=i)
    {
        p1=p1->next;
    }
    p2=p1;
    p1=p1->next;
    if(head->data==i)
    {
        head=head->next;
    }
    p2->next=p2->next->next;
    cout<<p1->data<<" ";
    delete p1;
    return head;
}


int main()
{
    cout<<"请输入总人数:"<<endl;
    node *head=List_create(),*p=head;
    cout<<"原始的编号排序为:"<<endl;
    traverse(head);
    cout<<endl;
    int origin,number;
    cout<<"请输入起始编号:";
    cin>>origin;
    cout<<"请输入出列号码:";
    cin>>number;
    while(p->next->data!=origin){p=p->next;}
    while(head->next!=head)
    {
        for(int i=0;i<(number-1);i++)
        {
            p=p->next;
        }
        head=List_delete(p->next->data,head);
    }
    cout<<"最后剩下的人的编号为:"<<head->data<<endl;
    return 0;
}

就需要实现的功能来说,此程序要实现这几个问题:
按自杀者编号的顺序建立一循环链表,时刻保证最后一人自杀之后能回到下一自杀的循环中(List_create);
定义一个函数,来遍历整个循环链表,以便于找到上述链表的头结点(traverse);
当有人自杀时,应该定义一个函数删除自杀者对应的结点(List_delete);
在主函数中,写一个算法,来表示上述自杀的规律,即隔着多少间隔自杀一人。

本人写所有代码的时间主要花费在链表的创建算法和自杀规律的表示算法上。读者自己写原创代码时请注意以下几点:
1、创建链表的函数中至少应该定义三个node指针,一个作为头结点的指针,另外两个作为创建链表时连接节点的指针,一旦定义的node指针少于三个,有可能出现找不到链表头结点或结点间失联的情况。链表的建立有头插法和尾插法两种,本人在源代码中使用的是尾插法;
2、main函数中head->next!=head的意思是头结点的next域指向头结点,即此时整个链表只剩下一个结点,该结点对应的人就是幸存者。

本人对百度百科中的日例子进行了一般化思考,即推广到n人自杀,规定间隔的情况。

此为本菜鸟首次发博,如有差错或不足,敬请谅解,并多加指点:)

猜你喜欢

转载自blog.csdn.net/Donald_Shallwing/article/details/82120086