/************************************************************************************************************
1、Josephus是公元1世纪的著名历史学家,相传在一次战役中他和另外几个人被围困在山洞里,
他们宁死不屈,决定站成一圈,每次数到三个人就杀一个,直到全部死光为止。Josephus和他的一个朋友不想死,
于是串通好了站在适当的位置上,最后只剩下他们俩的时候这个游戏就停止了。如果一开始的人数为N,
每次数到M个人就杀一个,那么要想不死应该站在什么位置呢?这个问题比较复杂,[具体数学]的1.3节研究了Josephus问题的解,有兴趣的读者可以参考。现在我们做个比较简单的练习,用链表模拟Josephus他们玩的这个游戏,
N和M作为命令行参数传入,每个人的编号依次是1~N,打印每次被杀者的编号,打印最后一个幸存者的编号。
用双向循环链表实现,代码如下:
**************************************************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef unsigned int ElemType;
typedef struct LinkList
{
ElemType elem;
struct LinkList *next;
struct LinkList *pre;
}LinkListNode, *LinkList;
void CreateLinkList(LinkList pHead, LinkList pTail, unsigned int all)
{
unsigned int i = 1;
LinkList tempNode = pHead;
for(i = 1; i <= all; i++)
{
LinkListNode * pNode = (LinkListNode *)malloc(sizeof(LinkListNode));
assert(pNode != NULL);
pNode->elem = i;
tempNode->next = pNode;
pNode->next = pTail;
pTail->pre = pNode;
pNode->pre = pHead;
tempNode = pNode;
}
pTail->next = pHead;
pHead->pre = pTail;
}
void DeleteNode(LinkList pHead, LinkList pTail, LinkList pDelNode)
{
LinkList pNode = pHead;
while(pNode->next != pDelNode)
{
pNode = pNode->next;
}
printf("The Delete Node is : %d \n", pDelNode->elem);
pNode->next = pDelNode->next;
pDelNode->next->pre = pNode;
free(pDelNode); /*记得要释放空间*/
}
void Remove(LinkList pHead, LinkList pTail, unsigned int all, unsigned int ave)
{
LinkList pNode = pHead->next;
unsigned int iCount = 0;
while(pHead->next != pTail) /*判断人被杀完的条件是:头结点的下一个结点是尾结点*/
{
if(iCount == ave)
{
DeleteNode(pHead, pTail, pNode);
iCount = 0; /*每移除一个后重新计数*/
}
pNode = pNode->next;
iCount ++;
if(pNode == pTail)
{
pNode = pHead->next; /*当移动到尾巴结点的时候,要指向头结点的下一个结点(第一个有效结点)*/
}
}
}
void InitLinkList(LinkList *pHead, LinkList *pTail)
{
*pHead = (LinkList)malloc(sizeof(LinkListNode));
*pTail = (LinkList)malloc(sizeof(LinkListNode));
if((NULL == *pHead) || (NULL == *pTail))
{
perror("malloc head node and tail node error ! \n");
exit(1);
}
(*pHead)->next = *pTail;
(*pTail)->next = *pHead;
(*pHead)->pre = *pTail;
(*pTail)->pre = *pHead;
}
void TraversalLinkList(LinkList pHead, LinkList pTail)
{
LinkList pNode = pHead->next;
while(pNode != pTail)
{
printf("%3d", pNode->elem);
pNode = pNode->next;
}
printf("\n\n");
}
void DestroyLinkList(LinkList pHead, LinkList pTail)
{
LinkList pNode = pHead;
LinkList pDelNode = pHead->next;
while(pDelNode != pTail)
{
pNode->next = pDelNode->next;
pDelNode->next->pre = pNode;
free(pDelNode);
pDelNode = pNode->next;
}
free(pHead);
free(pTail);
}
int main(void)
{
LinkList pHead = NULL;
LinkList pTail = NULL;
unsigned int all;
unsigned int ave;
printf("please input the number of all : ");
scanf("%u", &all);
printf("please input the average anumber : ");
scanf("%u", &ave);
InitLinkList(&pHead, &pTail); /*初始化头结点和尾结点*/
CreateLinkList(pHead, pTail, all); /*把所有的成员做成一个双向链表*/
TraversalLinkList(pHead, pTail);
Remove(pHead, pTail, all, ave); /*开始作移除操作*/
DestroyLinkList(pHead, pTail); /*销毁链表*/
return 0;
}
1、Josephus是公元1世纪的著名历史学家,相传在一次战役中他和另外几个人被围困在山洞里,
他们宁死不屈,决定站成一圈,每次数到三个人就杀一个,直到全部死光为止。Josephus和他的一个朋友不想死,
于是串通好了站在适当的位置上,最后只剩下他们俩的时候这个游戏就停止了。如果一开始的人数为N,
每次数到M个人就杀一个,那么要想不死应该站在什么位置呢?这个问题比较复杂,[具体数学]的1.3节研究了Josephus问题的解,有兴趣的读者可以参考。现在我们做个比较简单的练习,用链表模拟Josephus他们玩的这个游戏,
N和M作为命令行参数传入,每个人的编号依次是1~N,打印每次被杀者的编号,打印最后一个幸存者的编号。
用双向循环链表实现,代码如下:
**************************************************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef unsigned int ElemType;
typedef struct LinkList
{
ElemType elem;
struct LinkList *next;
struct LinkList *pre;
}LinkListNode, *LinkList;
void CreateLinkList(LinkList pHead, LinkList pTail, unsigned int all)
{
unsigned int i = 1;
LinkList tempNode = pHead;
for(i = 1; i <= all; i++)
{
LinkListNode * pNode = (LinkListNode *)malloc(sizeof(LinkListNode));
assert(pNode != NULL);
pNode->elem = i;
tempNode->next = pNode;
pNode->next = pTail;
pTail->pre = pNode;
pNode->pre = pHead;
tempNode = pNode;
}
pTail->next = pHead;
pHead->pre = pTail;
}
void DeleteNode(LinkList pHead, LinkList pTail, LinkList pDelNode)
{
LinkList pNode = pHead;
while(pNode->next != pDelNode)
{
pNode = pNode->next;
}
printf("The Delete Node is : %d \n", pDelNode->elem);
pNode->next = pDelNode->next;
pDelNode->next->pre = pNode;
free(pDelNode); /*记得要释放空间*/
}
void Remove(LinkList pHead, LinkList pTail, unsigned int all, unsigned int ave)
{
LinkList pNode = pHead->next;
unsigned int iCount = 0;
while(pHead->next != pTail) /*判断人被杀完的条件是:头结点的下一个结点是尾结点*/
{
if(iCount == ave)
{
DeleteNode(pHead, pTail, pNode);
iCount = 0; /*每移除一个后重新计数*/
}
pNode = pNode->next;
iCount ++;
if(pNode == pTail)
{
pNode = pHead->next; /*当移动到尾巴结点的时候,要指向头结点的下一个结点(第一个有效结点)*/
}
}
}
void InitLinkList(LinkList *pHead, LinkList *pTail)
{
*pHead = (LinkList)malloc(sizeof(LinkListNode));
*pTail = (LinkList)malloc(sizeof(LinkListNode));
if((NULL == *pHead) || (NULL == *pTail))
{
perror("malloc head node and tail node error ! \n");
exit(1);
}
(*pHead)->next = *pTail;
(*pTail)->next = *pHead;
(*pHead)->pre = *pTail;
(*pTail)->pre = *pHead;
}
void TraversalLinkList(LinkList pHead, LinkList pTail)
{
LinkList pNode = pHead->next;
while(pNode != pTail)
{
printf("%3d", pNode->elem);
pNode = pNode->next;
}
printf("\n\n");
}
void DestroyLinkList(LinkList pHead, LinkList pTail)
{
LinkList pNode = pHead;
LinkList pDelNode = pHead->next;
while(pDelNode != pTail)
{
pNode->next = pDelNode->next;
pDelNode->next->pre = pNode;
free(pDelNode);
pDelNode = pNode->next;
}
free(pHead);
free(pTail);
}
int main(void)
{
LinkList pHead = NULL;
LinkList pTail = NULL;
unsigned int all;
unsigned int ave;
printf("please input the number of all : ");
scanf("%u", &all);
printf("please input the average anumber : ");
scanf("%u", &ave);
InitLinkList(&pHead, &pTail); /*初始化头结点和尾结点*/
CreateLinkList(pHead, pTail, all); /*把所有的成员做成一个双向链表*/
TraversalLinkList(pHead, pTail);
Remove(pHead, pTail, all, ave); /*开始作移除操作*/
DestroyLinkList(pHead, pTail); /*销毁链表*/
return 0;
}