您的位置:首页 > 编程语言

“约瑟夫问题”实现代码

2009-03-10 21:29 330 查看
问题描述:

约瑟夫(Josephus)问题:设有n 个人围成一个圆圈,任意给定一个正整数m,从第一个人开始顺时针计数,计到第m个人,将其从圆圈中除去。然后再从下一个人开始,周而复始,直到圆圈中只剩一个人为止,那么剩下的那个人就是赢家。

代码实现:

#include <assert.h>
#include <iostream>
using namespace std;

struct Node 
{
    int Data;
    struct Node* next;
};

Node* CreateCircleList()
{
    Node* head = new Node;
    assert(head);
    head->next = NULL;

    int data;
    bool bInPuts = true;
    Node* q = head;

    while (bInPuts)
    {
        cin>>data;
        if (0 == data)
        {
            bInPuts = false;
        }
        else
        {
            Node* p = new Node;
            assert(p);
            p->Data = data;
            p->next = head;
            q->next = p;
            q = p;			
        }
    }
    return head;
}

int GetLength(Node* head)
{
    assert(head);

    int num = 0;
    Node* p = head->next;

    while (p != head)
    {
        num++;
        p = p->next;
    }

    return num;
}

/**
* @brief 该函数用来解决“约瑟夫问题”
* @return 返回循环链表的头指针
* @param[in] head 约瑟夫链
* @param[in] m 计数值
* @return 返回获胜者元素值

* @author wlq_729@163.com         
*      http://blog.csdn.net/rabbit729        
* @version 1.0          
* @date 2009-03-10  
*/
int Josephus(Node* head, const int m)
{
    assert(head);
    if (head->next == head)
    {
        cout<<"link is null!"<<endl;
        return -1;
    }

    int count = 0;

    Node* p = head;
    Node* prior = head;
    while (GetLength(head) > 1)
    {
        // 寻找待删除结点,p为待删除结点,prior为其前驱结点
        while (count < m)
        {
            count++;

            prior = p;
            p = p->next;

            // 考虑尾指针情况
            if (p == head)
            {
                prior = head;
                p = head->next;
            }		
        }

        // 删除结点
        cout<<"输出:"<<p->Data<<endl;
        prior->next = p->next;
        count = 0;
    }	
    return head->next->Data;
}

void Show(Node* head)
{
    assert(head);
    if (head->next == head)
    {
        cout<<"link is null!"<<endl;
        return;
    }

    Node* p = head->next;

    while (p != head)
    {
        cout<<p->Data<<endl;
        p = p->next;
    }
    return;
}

void main(void)
{
    // 建立循环链表
    Node* head = CreateCircleList();

    // 显示链表
    Show(head);

    // 求取获胜者
    int e = Josephus(head, 3);
    cout<<"获胜者为:"<<e<<endl;
}


程序输出结果:

假设链表为1,2,3,4,5,6。

则程序运行输出为:

1
2
3
4
5
6
输出:3
输出:6
输出:4
输出:2
输出:5
获胜者为:1
请按任意键继续. . .
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: