双向链表实现约瑟夫双向生死游戏

/*
  Name: 双向链表实现约瑟夫双向生死游戏 
  Description: 约瑟夫双向生死游戏是在约瑟夫生者死者游戏的基础上,正向计数后反向计数,
  然后再正向计数。具体描述如下:30个旅客同乘一条船,因为严重超载,加上风高浪大,危险万分;
  因此船长告诉乘客,只有将全船一半的旅客投入海中,其余人才能幸免遇难。无奈,大家只得同意这种办法,
  并议定30个人围成一圈,由第一个人开始,顺时针依次报数,数到第9人,便把他投入大海中,然后从他的下一个人数起,
  逆时针数到第5人,将他投入大海,然后从他逆时针的下一个人数起,顺时针数到第9人,再将他投入大海,如此循环,
  直到剩下15个乘客为止。问哪些位置是将被扔下大海的位置。
*/

#include<iostream>
using namespace std;

//===================================双向循环链表的结点类====================================

class Node
{
      friend class Doublelist;
      friend void DoubleJoseph();
      
      public:
             Node();
             int data;
             Node *prior;
             Node *next;
       private:
};

//=====================================双向循环链表类=========================================

class Doublelist
{
      friend void DoubleJoseph();
      public:
             void Creatlist(Doublelist &L);
             int getLength(Doublelist &L);
             Doublelist();
      private:
              Node *Head;
};

//=====================================Doublelist类的构造函数,初始化首结点数据=================

Node::Node()
{
            data = 0;
            prior = NULL;
            next = NULL;
}

//======================================Doublelist类的构造函数,初始化首结点数据=================

Doublelist::Doublelist()
{
                        Head = NULL;
}

//======================================建立双向循环链表=========================================

void Doublelist::Creatlist(Doublelist &L)
{
     cout << "请输入双向生死游戏的总人数N:";
     int n;
     cin >> n;
     Node *p,*s;
     for(int i = 1;i <= n;i++)
     {
             p = new Node;
             p->data = i;
             p->next = NULL;
             if(i == 1)
             {
                  L.Head = p; 
                  p->prior = NULL;
                  s = L.Head;
             }
             else
             {
                  s->next = p;
                  p->prior = s;
                  s = s->next;
             }  
     }
     s->next = L.Head;
     L.Head->prior = p;
}

//====================================获取双向链表的长度==============================

int Doublelist::getLength(Doublelist &L)
{
    Node *p = L.Head;
    int count = 0;
    while(p->next != L.Head)
    {
                  count++;
                  p = p->next;
    }
    count++;
    return count;
}

//=======================================实现约瑟夫双向生死游戏=========================

void DoubleJoseph()
{
     Doublelist L;
     L.Creatlist(L); 
     
     cout << "请输入游戏开始的位置S:";
     int s;
     cin >> s;
     
     cout << "请输入正向的死亡数字M:";
     int m;
     cin >> m;
     
     cout << "请输入逆向的死亡数字W:";
     int w;
     cin >> w;
     
     cout << "请输入剩余的生者人数";
     int k;
     cin >> k;
     cout << endl;
     
     Node *p,*q,*r;
     p = L.Head;
     for(int i = 0;i < s-1;i++)
     {
             p = p->next;
     }
     int t = 1;
     while(k < L.getLength(L))
     {
          if(t%2)//选择游戏方式
          {
                  //报数,寻找m结点 
                 for(int j = 0; j < m-1; j++)
                 {
                         q = p;
                         p = p->next;
                 }
                 //元素出列 
                 if(p == L.Head)
                 {
                         r = p;
                         L.Head = p->next;
                         q->next = p->next;
                         p->next->prior = q;
                         p = p->next;
                 }
                 else
                 {
                     r = p;
                     q->next = p->next;
                     p->next->prior = q;
                     p = p->next;
                 }
                 cout << "第" << t <<"个死者的位置是:" << r->data << '\n';
                 t++;
          }
          else
          {
              for(int j = 0;j < w - 1;j++)
              //报数,选择w结点 
              {
                               q = p;
                               p = p->prior;
              }
              //元素出列 
              if(p == L.Head)
              {
                   r = p;
                   L.Head = p->prior;
                   q->prior = p->prior;
                   p->prior->next = q;
                   p = p->prior;
              }
              else
              {
                  r = p;
                  q->prior = p->prior;
                  p->prior->next = q;
                  p = p->prior;
              }
              cout << "第" << t << "个死者的位置是:" << r->data <<endl;
              t++;
          }
     }
     cout << '\n' << "最后剩下:" << '\t' <<L.getLength(L) << "人" << endl;
     cout << "剩余的生者位置为:" << '\t';
     p = L.Head;
     
     while(p->next != L.Head)
     {
                   cout << p->data <<'\t';
                   p = p->next;
     }
     if(p)
     cout << p->data << '\t';
     cout << '\n';
}
//===============================================主函数,调用DoubleJoseph()函数==================================================

int main()
{
	cout << "现有N人围成一圈,从第S个人开始依次报数,正向报M的人出局,再由下一人开始报数,";
	cout << "逆时针数到的第W人出局。再从他逆时针的下一个人数起,顺时针数M人。";
	cout << "如此循环,直到剩下K个乘客为止。"<< '\n' << '\n';

	DoubleJoseph();
	
	system("pause");
	return 0;
}


转载于:https://my.oschina.net/clear/blog/54890

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值