循环链表处理约瑟夫环

来源:互联网 发布:浙江软件行业协会 编辑:程序博客网 时间:2024/06/03 03:34
#include <iostream>#include <string>using namespace std;/*据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。问题是,给定了和,一开始要站在什么地方才能避免被处决?*///模拟士兵typedef struct person{    string name;    int id;    person(string str,int id) :name(str),id(id){}    person():name(""),id(-1){}    bool operator==(const person& p){        return name == p.name && id == p.id;    }    friend ostream& operator<<(ostream& o, const person& p);}valuetype;ostream& operator<<(ostream& o, const person& p){    cout << "[" << p.name << " " << p.id << "]" << ends;    return o;}//链表节点typedef struct _node{    valuetype data;    _node* pnext;    _node(valuetype e, _node* p = nullptr):data(e),pnext(p){}}node;//循环链表类class circlelist{public:    circlelist();    ~circlelist();    void append(valuetype e);    void insert(int index, valuetype e);    void remove(valuetype e);    void earse(int index);    node& serach(int index);    int find(valuetype e);    void replace(valuetype olddata, valuetype newdata);    void modify(int index, valuetype newdata);    int empty(){ return m_head == nullptr; }    int length(){ return m_length; }    void print();protected:    node* m_head;    node* m_tail;    int m_length;};circlelist::circlelist() :m_head(new node(valuetype())), m_tail(m_head), m_length(0){}circlelist::~circlelist(){    while (m_head->pnext != m_head){        node* pdel = m_head->pnext;        m_head->pnext = pdel->pnext;         delete pdel;    }    delete m_head;    m_head = nullptr;}void circlelist::append(valuetype e){    ++m_length;     m_tail->pnext = new node(e);    m_tail = m_tail->pnext;    m_tail->pnext = m_head; }void circlelist::insert(int index, valuetype e){    if (index < 0 || index > length()){        cout << "index is out of range.\n";    }    else{        node* pnew = new node(e);        node* p = m_head;        for (int i = 0; i < index; ++i){            p = p->pnext;        }        pnew->pnext = p->pnext;        p->pnext = pnew;        if (pnew->pnext == m_head){            m_tail = pnew;        }        ++m_length;    }}void circlelist::remove(valuetype e){    node* p = m_head;    while (p->pnext != m_head){        if (p->pnext->data == e){            node* pdel = p->pnext;            p->pnext = pdel->pnext;            delete pdel;            --m_length;        }        else{            p = p->pnext;        }    }}void circlelist::earse(int index){    if (index < 0 || index > m_length - 1){        cout << "index is out of range.\n";    }    else{        node* p = m_head;        for (int i = 0; i < index; ++i){            p = p->pnext;        }        node* pdel = p->pnext;        p->pnext = pdel->pnext;        delete pdel;        --m_length;    }}node& circlelist::serach(int index){    if (index < 0 || index > m_length - 1){        cout << "index is out of range.\n";        return *m_head;    }    else{        node* p = m_head;        for (int i = 0; i < index; ++i){            p = p->pnext;        }        return  *p->pnext;    }}int  circlelist::find(valuetype e){     node* p = m_head;    for (int i = 0; i < m_length; ++i){        if (p->pnext->data == e){            return i;        }        p = p->pnext;    }    return  -1; }void circlelist::replace(valuetype olddata, valuetype newdata){    node* p = m_head;    for (int i = 0; i < m_length; ++i){        if (p->pnext->data == olddata){            p->pnext->data = newdata;        }        p = p->pnext;    }}void circlelist::modify(int index, valuetype newdata){    if (index < 0 || index > m_length - 1){        cout << "index is out of range.\n";    }    else{        node* p = m_head;        for (int i = 0; i < index; ++i){            p = p->pnext;        }        p->pnext->data = newdata;    }}void circlelist::print(){    node* p = m_head;    while (p->pnext != m_head){        cout << p->pnext->data << ends;        p = p->pnext;    }    cout << endl;}//约瑟夫环类class Josephus : public circlelist {public:    Josephus(int number,int killednumder):m_number(number),m_ikilled(killednumder){        int size = 0;        while (number != 0){            number /= 10;            ++size;        }        char* buf = new char[size+1];        for (int i = 1; i <= m_number; ++i){            string str("person");            _itoa_s(i, buf, size+1, 10);            str.append(buf);            append(person(str,i));//模拟士兵加入到循环链表中        }        delete buf;    }    void start(int start_person);//从第start_person个人开始数private:    int m_ikilled;//数到m_ikilled杀掉一个士兵    int m_number;//士兵的个数};void Josephus::start(int start_person){    int count = 1;    node* temp = m_head;    start_person = (start_person - 1) % m_length;    //找到开始数数的士兵的前一个士兵    for (int i = 0; i < start_person; ++i){        temp = temp->pnext;    }    cout << "\t\t\tstart\n";    print();    //直到只有一个士兵    while (m_head->pnext->pnext != m_head){        for (int i = 0; i < m_ikilled-1; ++i){            temp = temp->pnext;            if (temp == m_head){                temp = temp->pnext;//头结点跳过            }        }        node* pdel = temp->pnext;        if (pdel == m_head){//跳过头结点,即杀掉的士兵是链表的第一个节点            pdel = pdel->pnext;            temp = temp->pnext;        }        temp->pnext = pdel->pnext;              --m_length;        cout << "\t\t\t第" << count++ << "次\t删除 ";        cout << pdel->data << endl;//杀掉的士兵        delete pdel;        print();    }    cout << "\t\t\talive person: ";    print();}int main(){    Josephus j(6, 3);//6个士兵,数到3    j.start(3);//从第3个人开始数    return 0;}

这里写图片描述

原创粉丝点击