约瑟夫(Jonsephus)问题描述
n个人围成一个环,从第i个开始,由1至interval不断报数,凡报到interval的出列,直到环空为止。
例如:总共有8个人围成一个环,取间隔未3。假设从第1个人开始报数,当有人报的3的时候,这个人出列。从下个人再次进行报数,依次类推,当剩下最后一人时直接出列。
输入1 2 3 4 5 6 7 8 ,取间隔为3,则输出序列为3 6 1 5 2 8 4 7。
对数据进行操作:
首先确定从那个位置开始报数
while(表结点数>1)
{
for(1 到间隔数)
{
记录节点数目;
输出并删除该结点;
}
}
输出并删除最后一个结点;
#include <iostream>
#include <iomanip>
using namespace std ;
struct Jonse
{ int code ;
Jonse *next;
};
Jonse * CreateList( int );
void PrintList(Jonse *);
void Out(Jonse *, int, int ) ;
int main()
{
Jonse * head ;
int num , interva , begin ;
cout << "\n请输入数字总数:\n" ;
cin >> num ;
head = CreateList(num) ; //创建链表
PrintList(head) ; //打印链表信息
cout << "\n输入计数位置:\n" ;
cin >> begin ;
cout << "\n输入打印间隔:\n" ;
cin >> interva ;
cout << "输出序列:\n" ;
Out( head, begin, interva ) ;
}
Jonse * CreateList ( int n )//创建N个结点的单项循环链表 ,头插法
{
Jonse *head, *p ; // 声明局部变量的链表指针
head= new Jonse ;
p = head;
for ( int i=1;i<=n;i++)
{
p->code = i ;
if (i<n)
{
p->next =new Jonse; //使用P指针来建立后续结点
p = p->next;
}
}
p->next = head; //构成循环链表
return head; //返回头指针
}
void PrintList(Jonse *head)
{
Jonse *p;
p=head;
do{
cout << p->code << '\t' ;
p = p->next ;
} while(p!=head) ;
}
void Out(Jonse *head, int i, int d)
{
Jonse *p,*q ;
int k ;
p = head;
for( q = head ;q->next != head;q=q->next) ; //建立双跟踪指针,寻找P的前置
for( k = 1; k<i; k++) //寻找开始位置
{
q=p;
p=p->next;
}
while(p!= p->next)//当剩下最后一个结点的时候跳出循环
{
for (k=1;k<d;k++) //计数,输出间隔位置的结点值
{
q = p ;
p=p->next ;
}
cout<<p->code<< '\t' ;
q->next = p->next ;//删除结点
delete p ;//释放空间
p = q->next ;//移动指针
}
cout << p->code << endl ;//输出并删除最后一个结点
delete p ;
}
参考书籍《C++ 程序设计基础》周霭如。[^2]