利用
循环链表类
实现约瑟夫退圈问题:
n
个人 (不同 id
)围成一个圈,从
startId(
任意数
)
个开始报数
m(
任意数
)
个 数,数 m
的人出列排成新队列,
m
清零,然后又从下一个人开始数 m 个数开始,数到
m
就出列接在新队列尾部,如此重复,直到所有人都出列为止,请输出出列的次序
(依次输出出列人员的编号)
代码如下:
#include<iostream>
#include<iomanip>
#include<string>
using namespace std;
class CNode
{
public:
int data;
CNode * next;
CNode() {}
~CNode() {}
};
class CLinkList
{
private:
CNode* headNode ; //头结点
int m; //报数人数
int k; //总人数
int startId; //开始报数人的ID
public:
CLinkList() {}
void BuildLinkList(); //链表的创建
void DelNode( int a ); //删除结点
void Joseph(); //实现约瑟夫退圈问题
~CLinkList(){} //析构,释放内存
};
void CLinkList::BuildLinkList( )
{
headNode = new CNode;
headNode->next = NULL;
headNode->data = 1;
CNode *p = headNode, *q;
int i;
for( i=2; i<=k; i++ )
{
q = new CNode;
q->data = i;
q->next = NULL;
p->next = q;
p = q;
}
p->next = headNode; //最后一个结点连接头结点,实现链表循环
}
void CLinkList::Joseph() //实现约瑟夫退圈问题
{
cout<<" 约瑟夫退圈问题 "<<endl;
cout<<"请输入总人数,报数人数:";
cin>>k>>m;
if( m>k )
{
m = m % k;
}
BuildLinkList();
cout<<"请输入开始退圈人的ID:";
cin>>startId;
if( startId>k )
{
startId = startId % k;
}
CNode *p = headNode, *q;
while( p->data != startId )
{
p = p->next;
}
p = p->next;
cout<<"依次退圈的人:"<<endl;
int i = 0; //记录报数
int s = 0; //记录退圈人数
while( s<k )
{
i++;
q = p;
p = p->next;
if( i == m )
{
s++;
cout<<q->data<<"号"<<endl;
DelNode( q->data );
i = 0;
}
}
}
void CLinkList::DelNode( int a )
{
CNode *p = headNode, *q, *d;
if( headNode->data == a )
{
while( p->next != headNode )
{
p = p->next;
}
d = headNode;
headNode = headNode->next;
p->next = headNode;
delete d;
}
else
{
while( p->data != a )
{
q = p;
p = p->next;
}
d = p;
q->next = p->next;
delete d;
}
}
int main()
{
CLinkList cli;
cli.Joseph();
return 0;
}