1、约瑟夫环问题
约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。
2、原理
约瑟夫环运作如下:
1、一群人围在一起坐成环状(如:N)
2、从某个编号开始报数(如:K)
3、数到某个数(如:M)的时候,此人出列。
4、一直循环,直到所有人出列。
3、实现代码
#include<iostream>
#include<assert.h>
using namespace std;
typedef int DataType;
typedef struct Node
{
DataType data;
struct Node* next;
}Node, *PNode;
void InitSeqList(PNode *pHead)//初始化链表
{
assert(pHead);//指针不为空
*pHead = NULL;
}
PNode BuyBode(DataType data)//创建新节点
{
PNode PTemp = (PNode)malloc(sizeof(Node));//为PTemp分配空间
if (PTemp)//空间分配成功
{
PTemp->data = data;
PTemp->next = NULL;
return PTemp;//新节点创建成功,返回新节点
}
else
{
return NULL;
}
}
void Pushback(PNode *pHead, DataType data)//尾部插入节点
{
assert(pHead);
if (*pHead == NULL)//如果要插入节点的链表为空
{
*pHead = BuyBode(data);//头指针指向该节点,也就是头结点
}
else
{
PNode PTailNode = *pHead;
while (PTailNode->next)//寻找原链表最后一个节点
{
PTailNode = PTailNode->next;
}
PTailNode->next = BuyBode(data);//该节点插入到原链表的的最后一个节点之后
}
}
void JosephCircle(PNode pHead, int M)//约瑟夫环问题
{
int Order = 0;
int count = 0;
PNode pos = pHead;
PNode pDealNode = NULL;
assert(pHead);//判断指针不为空
if (pHead == NULL || M <= 0)//链表无效或报数无效
{
return;
}
while (pos->next)//单链表连成循环链表
{
pos = pos->next;
}
pos->next = pHead;
while (pos != pos->next)//直到最后一个人循环终止
{
count = M;
while (--count)//找到出列的人,注意 :--count指的是删除位置减一
{
pos = pos->next;
}
pDealNode = pos->next;//保留要删除的节点
pos->next = pDealNode->next;//该节点的前驱指向该节点的后继,也就是说删除当前节点
Order++;
printf("第%d个出列的序号是:%d\n", Order, pDealNode->data);//输出出列的序号
free(pDealNode);//释放删除的节点
}
printf("最后一个节点出列序号是:%d\n", pos->data);//输出最后一个人出列的序号
free(pos);//释放最后一个节点
}
void FunTest()
{
PNode pHead;
InitSeqList(&pHead);
for (int idx = 0; idx < 10; idx++)
{
Pushback(&pHead,idx);
}
JosephCircle(pHead, 3);
}
int main()
{
FunTest();
system("pause");
return 0;
}