Josephus(约瑟夫环)问题

#include<iostream>
using namespace std;
//链表结点kid,其中number为这个人的编号
struct kid
{
    int number;
    kid *next;
};
//约瑟夫环类
class joseph_ring
{
private:
    int n;//用于存放人数
    int m;//用于存放初始密码
    kid *head;//链表的头结点,初始化时指向1号孩子
public:
    joseph_ring(int nn, int mm);//创建nn个孩子,间隔为mm的约瑟夫环
    ~joseph_ring();
    void show();//运算并输出的成员函数
};
//定义joseph_ring类中的成员函数
  joseph_ring::joseph_ring(int nn, int mm):n(nn),m(mm){}
  joseph_ring::~joseph_ring()
 {
// 	for(int i=1;i<=n;i++)
//	{
//		kid *pt=head;
//		delete  pt;
//		head=head->next;
//	}
 }
 void  joseph_ring::show()
 {
 	kid *p,*q;
 	for(int i=0;i<n;i++)//首先连接结点,并且为每个结点编号
 	{
 		p=new kid;
 		if(i==0)
		{
				head=p;
 		        head->number=i+1;
		}
		else
		{
			q->next=p;
			q->next->number=i+1;
		}
		q=p;
 	}
 	q->next=head;//首尾相连,成环。。
// 	kid *pp1=head;
// 	for(int i=0;i<n;i++)//显示每个结点编号
//	{
//		cout<<pp1->number;
//		pp1=pp1->next;
//	}
//	cout<<endl;
//	int mm=0;
	kid *pt=head;
	kid*pt2;
//	for(int i=m;i<n&&n-mm>2;i=(i+m)%n)//之前这么写是想按照i的值来删除结点
	for(int i=1;i<n;i++)
	{
		for(int j=0;j<m-2;j++)
			{
				pt=pt->next;//删除某个点,需要指向其前一个点,所以少循环一次
            }
	    kid *del=pt->next;
	    pt->next=pt->next->next;
	     cout<<del->number<<"\t";
	    delete del;
	    pt2=pt;
	    pt=pt->next;
//	    ++mm;
	}
	//cout<<"mm="<<mm<<endl;
	cout<<endl;
	cout<<"最后剩余结点编号为:"<<pt2->number<<endl;
//	kid *pp2=head;
// 	for(int i=0;i<n-mm;i++)
//	{
//		cout<<pp2->number;
//		pp2=pp2->next;
//	}
 }
int main()
{
    int n,m;
    while(1)
    {
      cout<<"n=";
      cin>>n;
      cout<<"m=";
      cin>>m;
      joseph_ring j(n,m);
      j.show();
    }
    return 0;
}

原题链接:http://blog.csdn.net/sxhelijian/article/details/9052891

整理后的版本:

#include<iostream>
using namespace std;
//链表结点kid,其中number为这个人的编号
struct kid
{
    int number;
    kid *next;
};
//约瑟夫环类
class joseph_ring
{
private:
    int n;//用于存放人数
    int m;//用于存放初始密码
    kid *head;//链表的头结点,初始化时指向1号孩子
public:
    joseph_ring(int nn, int mm);//创建nn个孩子,间隔为mm的约瑟夫环
    ~joseph_ring();
    void show();//运算并输出的成员函数
};
//定义joseph_ring类中的成员函数
  joseph_ring::joseph_ring(int nn, int mm):n(nn),m(mm)
  {
  	kid *p,*q;
 	for(int i=0;i<n;i++)//首先连接结点,并且为每个结点编号
 	{
 		p=new kid;
 		if(i==0)
		{
				head=p;
 		        head->number=i+1;
		}
		else
		{
			q->next=p;
			q->next->number=i+1;
		}
		q=p;
 	}
 	q->next=head;//首尾相连,成环。。
  }
  joseph_ring::~joseph_ring()
 {
 	delete head;
    head=NULL;
 }
 void  joseph_ring::show()
 {
	kid *pt=head;
	kid*pt2;
	for(int i=1;i<n;i++)
	{
		for(int j=0;j<m-2;j++)
			{
				pt=pt->next;//删除某个点,需要指向其前一个点,所以少循环一次
            }
	    kid *del=pt->next;
	    pt->next=pt->next->next;
	     cout<<del->number<<"\t";
	    delete del;
	    pt2=pt;
	    pt=pt->next;
	}
	cout<<endl;
	cout<<"最后剩余结点编号为:"<<pt2->number<<endl;
	head=pt;
	pt=pt2=NULL;
 }
int main()
{
    int n,m;
    while(1)
    {
      cout<<"n=";
      cin>>n;
      cout<<"m=";
      cin>>m;
      joseph_ring j(n,m);
      j.show();
    }
    return 0;
}
所给答案中的show函数:

void joseph_ring::show()  //执行出圈操作  
{  
    kid *p1,*p2,*p;  
    int count;  
    p1=head;  
    for(int i=1; i<=n-1; i++)//有n个人,所以执行n-1次循环,删除n-1个人  
    {  
        count=1;  //用count定位到第m个人,循环后,p1指向这个人,p2指向这个人的上一个人  
        while(count<m)  
        {  
            p2=p1;  //p2指向前一个  
            p1=p1->next;  
            count++;  
        }  
        cout<<p1->number<<"\t";//这指向的是当前要删除人  
        p=p1;//p指向当前这个人  
        p2->next=p1->next;//将当前出圈人的直接前驱和直接后继连接起来  
        p1=p1->next;//下次从当前人的下一个人开始数  
        delete p;//释放内存  
    }  
    cout<<endl;  
    cout<<"The last one is No. "<<p1->number<<endl;  
    head=p1; //环中只剩下了一个结点  
}  



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值