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

“约瑟夫问题”实现代码

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

约瑟夫(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
请按任意键继续. . .
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: