数据结构Review——线性表练习(约瑟夫问题)

题目来源:中国大学MOOC - 北京大学《数据结构与算法》- 第二章 线性表编程作业

3、约瑟夫问题(10分)

题目内容:

有n只猴子,按顺时针方向围成一圈选大王(编号从1到n),从第1号开始报数,一直数到m,数到m的猴子退出圈外,剩下的猴子再接着从1开始报数。就这样,直到圈内只剩下一只猴子时,这个猴子就是猴王,编程求输入n,m后,输出最后猴王的编号。

输入格式:

输入包含两个整数,第一个是n,第二个是m (0 < m,n <=300)。

输出格式:

输出包含一行,即最后猴王的编号。

输入样例:18 2

输出样例:5

时间限制:500ms内存限制:32000kb

思路:因涉及节点的删除操作以及循环遍历数据的操作,我采用循环双链表进行数据存储和处理。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>

using namespace std;

void solution();

//定义双循环链表节点
typedef struct Node
{
    int number;
    struct Node *next;
    struct Node *prev;

    Node()
    {
        number = 0;
        prev = next = NULL;
    }

    Node(int n)
    {
        number = n;
        prev = next = NULL;
    }
} Node;

//定义猴子序列的双循环链表类
class MonkeyList
{
private:
    Node *head;
    Node *rear;
    int len;
    
    //将序号为num的元素从链表中删除,即被淘汰
    bool remove(int num)
    {
        Node *p = head;
        do
        {
            if (p->number == num)
            {
                p->prev->next = p->next;
                p->next->prev = p->prev;

                if (p == head)
                {
                    head = p->next;
                }
                if (p == rear)
                {
                    rear = p->prev;
                }
                delete p;
                len--;
                // cout << num << " has been deleted." << endl;
                return true;
            }
            p = p->next;
        } while (p != head);

        return false;
    }

public:
    MonkeyList()
    {
        len = 0;
        head = rear = NULL;
    }
    MonkeyList(int l)
    {
        len = l;
        if (len == 0)
        {
            head = rear = NULL;
            return;
        }
        head = new Node(1);
        rear = head;
        for (int i = 2; i <= len; i++)
        {
            Node *node = new Node(i);
            node->next = head;
            head->prev = node;
            rear->next = node;
            node->prev = rear;

            rear = rear->next;
        }
    }
    
    //依次报数,报到m的被删除
    void countOff(int m)
    {
        Node *p = head;
        int i = 1;
        while (len > 1)
        {
            if (i == m)
            {
                Node *tmp = p->next;
                remove(p->number);
                p = tmp;
                i = 1;
                continue;
            }
            p = p->next;
            i++;
        }
        cout << head->number << endl;
    }
};

int main()
{
    int T = 0;
    int t = 0;

    T = 1;
    while (t < T)
    {
        solution();
        t++;
    }

    system("pause");
    return 0;
}

void solution()
{
    int m, n;
    cin >> n >> m;
    MonkeyList *list = new MonkeyList(n);
    list->countOff(m);
}

猜你喜欢

转载自blog.csdn.net/kingslave1/article/details/93708893