约瑟夫环(循环链表)

Posted mayfly-nymph

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了约瑟夫环(循环链表)相关的知识,希望对你有一定的参考价值。

约瑟夫环问题,是一个经典的循环链表问题,题意是:已知 n 个人(分别用编号 1,2,3,…,n 表示)围坐在一张圆桌周围,从编号为 k 的人开始顺时针报数,数到 m 的那个人出列;他的下一个人又从 1 开始,还是顺时针开始报数,数到 m 的那个人又出列;依次重复下去,直到圆桌上剩余一个人。

 

#include <iostream>

using namespace std;

struct person {
    int number;
    person *next;
};

person* initLink(int n) {
    person* head = new person;//定义首元节点
    head->number = 1;
    head->next = NULL;
    person* temp = head;
    for (int i = 2; i <= n; ++i) {//定义后面n-1个节点
        person* body = new person;
        body->number = i;
        body->next = NULL;
        temp->next = body;
        temp = temp->next;
    }
    temp->next = head;//首尾相连

    return head;
}

void FindAndDelete(person* head, int n, int num) {
    person* temp = head;
    while (temp->next != head) {//定位到首元节点前一节点
        temp = temp->next;
    }
    person* temp2 = head;
    while (temp2->number != n) {//定一个指针指向起始节点,一个定位到起始节点前一节点,为删除节点准备
        temp = temp2;
        temp2 = temp2->next;
    }
    while (temp2->next != temp2) {//当一个循环链表的节点->next指向自身,说明只剩一个节点
        for (int i = 1; i < num; ++i) {//一个节点定位到数到num的节点,一个定位到前一节点
            temp = temp2;
            temp2 = temp->next;
        }
        temp->next = temp2->next;//删除num节点
        cout << "序号为:" << temp2->number << "出列" << endl;//删除的节点为出列序列
        delete temp2;
        temp2 = temp->next;//从下一节点继续开始
    }
    cout << "最后剩下的同学序列是:" << temp2->number << endl;
    delete temp2;
}

int main()
{
    int n, k, num;
    cout << "请输入几位同学:";
    cin >> n;
    person* stu = initLink(n);
    cout << "请输入起始序列号(1~" << n << "):";
    cin >> k;
    cout << "请输入数到几出列:";
    cin >> num;
    FindAndDelete(stu, k, num);

    system("PAUSE");
    return 0;
}

 

以上是关于约瑟夫环(循环链表)的主要内容,如果未能解决你的问题,请参考以下文章

循环链表实现约瑟夫环

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

使用循环链表实现约瑟夫环(围圈报数问题)

暑假OJ练习——8 圆桌问题(使用循环链表解决约瑟夫环问题)

约瑟夫环(循环链表)

Java循环链表实现约瑟夫环(搬运)