已知 n 个人(以编号1, 2, 3 ,4, 5 ,6 ... .. .n)围坐一张圆桌周围。从编号为k 的人开始报数,数到m 的那个人出列;他的下一个人又从 1开始报数,数到m的那个人又出列;依次规律重复下去,直到圆桌周围的人全部出列。请用C++编程。
整个程序分为3个步骤:
第一步:建立一个有n个元素的循环链表,链表是从1的编号开始的。
第二步:是从链表的表头数到第 k 个值。
第三步:从 k 的后面开始输入 m 个值,删除该值,继续开始数,继续删。。。。。。。,直到删除完。
#include <iostream>
using namespace std;
#define ERROR 0
typedef struct LNode
{
int data;
struct LNode *link;
LNode()
{
data = 0;
link = NULL;
}
}LNode,*LinkList;
/************************************************************************/
/* n 为总人数 */
/* k 为第一个开始报数的人 */
/* m为出列者喊到的数 */
/************************************************************************/
void Josephus(int n,int k,int m)
{
//pnode 为当前节点,secondnode为辅助节点,指向pnode的前驱节点,list为头结点
if(n<0||k<0||m<0) return;
LinkList pnode,prenode,curr;
pnode = new LNode();
pnode->data = 1;
pnode->link = pnode; //建立一个循环链表
curr = pnode;
for (int i=2;i<=n;i++)
{
LinkList temp = new LNode();
temp->data = i;
temp->link = curr->link;
curr->link = temp;
curr = temp;
}
prenode = curr;
while(k--)
{
prenode = pnode; //prenode是pnode的前一个结点。
pnode = pnode->link; //移动结点 pnode是第k个元素
}
while(n--)
{
//for 是移动m个位置pnode是移动到的m位置,prenode是pnode的前一个结点
for (int s=m;--s;prenode = pnode,pnode = pnode->link);
prenode->link = pnode->link; //删除pnode结点
printf("%d ",pnode->data); //打印删除的结点
free(pnode); //释放空间
pnode = prenode->link; //从prenode的下一个结点开始,数一个m个结点的值。
}
}
void main()
{
Josephus(5,3,1);
system("pause");
}
运行的结果: