约瑟夫问题是list链表的应用之一,问题描述:N个人围成一个圆圈,每个人都有唯一的一个编号,编号从1到N,从编号为1的人开始报数,依次报到K,报数为K的人出列,他的下一个又从1开始报数,直到所有的人都出列,求这个出列的序列。结合上一篇博客,这里使用list链表,给出一个可行的解答代码。
注:n为人数,p为要报的数。
#include<iostream>
#include<list>
using namespace std;
int main()
{
int n,p;
list<int> l;
while(cin>>n>>p)
{
l.clear();
for(int i=1;i<=n;i++)
{
l.push_back(i);
}
list<int>::iterator it,pdel;
it=l.begin();
while(l.size()!=1)
{
//报数,it指向要删除的元素
for(i=1;i<p;i++)
{
it++;
if(it==l.end())
it=l.begin();
}
//删除处理
cout<<*it<<"->";
pdel=it;
it++;
it= (it==l.end()) ? l.begin() : it;
l.erase(pdel);
}
cout<<*it<<endl;
}
return 0;
}
Java版本的简单约瑟夫环:
public class test
{
public static void main(String[] args)
{
CycLink cyclink=new CycLink();
cyclink.setLength(5);
cyclink.createLink();
cyclink.printLink();
cyclink.setK(2);
cyclink.setM(2);
cyclink.play();
}
}
class Child
{
int number;
Child nextChild;
public Child(int number)
{
this.number=number;
}
}
//环形链表
class CycLink
{
//环形链表大小
//指向第一个小孩的应用不能动
int length=0;
int k=0;
int m=0;
Child firstChild=null;
Child temp=null;
//设置链表大小
public void setLength(int length)
{
this.length=length;
}
public void setK(int k)
{
this.k=k;
}
public void setM(int m)
{
this.m=m;
}
//初始化环形链表
public void createLink()
{
for(int i=1;i<=length;i++)
{
//创建第一个小孩
if(i==1)
{
Child child=new Child(i);
this.firstChild=child;
this.temp=child;
}
else
{
Child child=new Child(i);
this.temp.nextChild=child;
this.temp=child;
if(i==this.length)
{
//创建最后一个小孩
this.temp.nextChild=this.firstChild;
}
}
}
}
public void printLink()
{
Child temp=this.firstChild;
do
{
System.out.print(temp.number+" ");
temp=temp.nextChild;
}while(temp!=firstChild);
System.out.println();
}
public void play()
{
Child temp=this.firstChild;
//找到数数的结点
for(int i=1;i<k;i++)
{
temp=temp.nextChild;
}
while(this.length!=1)
{
//数m下
for(int j=1;j<m;j++)
{
temp=temp.nextChild;
}
//找到出圈的前一个结点
Child temp1=temp;
while(temp1.nextChild!=temp)
{
temp1=temp1.nextChild;
}
//将数m的结点删除
temp1.nextChild=temp.nextChild;
temp=temp.nextChild;
//this.printLink();
this.length--;
}
//最后一个结点
System.out.println(temp.number);
}
}
约瑟夫问题还有其它变形,如从第M个开始报数或者当某个人出队后重新给定下一次报数的值等,只需要在第一个C++程序的基础上做修改即可。