IE盒子

搜索
查看: 125|回复: 0

使用C++双链表实现:约瑟夫问题

[复制链接]

2

主题

7

帖子

12

积分

新手上路

Rank: 1

积分
12
发表于 2023-4-16 00:30:48 | 显示全部楼层 |阅读模式
这段代码是使用双向循环链表实现约瑟夫问题的一个例子。具体来说,给定n个人,编号为1~n,在这n个人中按顺序围成一圈,从第1个人开始报数,每报数到m的人将出列,然后从下一个人重新开始报数,直到所有人都出列。要求依次输出出列的人的编号。
解题思路:

我们可以创建一个带有n个节点的双向循环链表来模拟这个过程,每个节点表示一个人。
在代码中,我们先创建一个头结点head,并用一个指针prev来指向最后一个节点,然后循环从2到n,创建新的节点curr,并将prev的next指向curr,curr的prev指向prev,再将prev更新为curr,这样就创建了一个带有n个节点的双向循环链表。
最后,将prev的next指向head,head的prev指向prev,把链表闭合成环。
接着,我们定义一个指针curr来指向当前处理的节点,它初始指向head。我们需要循环遍历整个链表,每次找到要出列的节点的前一个节点,即从curr开始顺时针遍历m-1个节点,然后输出并删除该节点。
删除节点时,我们需要保存要删除的节点的指针temp,然后把curr的next指向temp的next,temp的next的prev指向curr,最后释放temp所占用的内存。循环这个过程,直到所有的节点都被删除。

注意,由于这个双向循环链表是动态分配内存的,我们需要在程序结束时手动释放节点所占用的内存。此处释放内存时需要使用一个do-while循环来遍历整个链表,并且要判断链表是否已经遍历完了一圈(即当前节点是否等于头结点),才能正确地释放内存。

时间复杂度:

由于每次需要遍历m个节点来找到要出列的节点,因此总共需要遍历n * m个节点。因此时间复杂度为O(nm)。
源码:

#include <iostream>
using namespace std;

struct Node {
    int data;
    Node* prev;
    Node* next;
    Node(int d): data(d), prev(nullptr), next(nullptr) {}
};

void josephus(int n, int m) {
    Node* head = new Node(1);
    Node* prev = head;
    for (int i = 2; i <= n; i++) {
        Node* curr = new Node(i);
        prev->next = curr;
        curr->prev = prev;
        prev = curr;
    }
    prev->next = head;  // 将链表闭合成环
    head->prev = prev;
   
    Node* curr = head;
    while (n > 0) {
        // 找到要出列的节点的前一个节点
        for (int i = 0; i < m-1; i++) {
            curr = curr->next;
        }
        // 输出并删除节点
        cout << curr->next->data << " ";
        Node* temp = curr->next;
        curr->next = temp->next;
        temp->next->prev = curr;
        delete temp;
        n--;
    }

    // 释放内存
    Node* temp = head;
    do {
        Node* next = temp->next;
        delete temp;
        temp = next;
    } while (temp != head);
}

int main() {
    josephus(5, 3);  // 输出: 3 1 5 2 4
    return 0;
}
该代码首先创建了一个带有n个节点的双链表,然后找到要出列的节点的前一个节点,输出并删除该节点,直到所有的节点都被删除。由于每次需要遍历m个节点来找到要出列的节点,因此时间复杂度为O(nm)。注意在最后需要释放内存。

公众号:奇牛编程
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表