ACM学习历程16——List链表的应用之简单约瑟夫问题

约瑟夫问题是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;
}

《ACM学习历程16——List链表的应用之简单约瑟夫问题》

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++程序的基础上做修改即可。

    原文作者:约瑟夫环问题
    原文地址: https://blog.csdn.net/u010480899/article/details/52318584
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞