C++解决约瑟夫环(史上最清晰)

  

#include<iostream.h>
struct Node
{
  int data;
  Node *pNext;
};

 

void main()
{

 

  //1定义环的相关参数
  //a.环的节点数
  //b.开始点数的位置
  //c.出环间距。

 

  int n,k,m,i;
  Node *p,*q,*head; //p为一个中间变量,用来临时处理
  cout<<"输入n的值:";
  cin>>n;
  cout<<"输入起始报数人号码k的值:";
  cin>>k;
  cout<<"输入 数到m出列的m的值:";
  cin>>m;

 

  //2生成约瑟夫环
  //a.头节点
  //b.中间变量
  //c.每一个环节点操作
  //d.将最后一个换节点的下一个指针的地址指向头节点
  head=(Node*)new Node; //确定头结点
  p=head; //为临时变量赋初值
  for(i=1;i<=n-1;i++)
  {
    p->data=i;
    p->pNext=(Node*)new Node; //为下一个新建内存
    p=p->pNext; //将下一个节点的地址赋给临时变量,准备下一步的处理
  }
  p->data=n; //最后一个单独处理
  p->pNext=head; //指向头,形成循环链表
  p=head;

 

  while(p->data!=(p->pNext)->data)//p->data==(p->pNext)->data表示只剩下一个结点的
  {
    //3.找到开始数数的位置

    p = head; //将p指向Head,表示从N开始
    while(p->data !=k) //寻找编号为k的结点,最后两步 k=(q->pNext)->data和 p->pNext=q->pNext跟这里呼应,以免每次都进入这个循环
    p=p->pNext;

    //4.如果步长为1则,直接输出
    //否则:(因为这一步首先报到m-1,所以上一个步骤就有必要了(步长为1的情况))
    //a.找到出列环的前一个节点p
    //b.找到出列环的节点n
    //c.报数
    //d.将出列环的上一个节点p的next指针指向n的next。
    //e.删除该出列环节点
    if(m==1)
    {
    for(i=1;i<=n;i++)
    {
      cout<<p->data<<'\t' ;
      p=p->pNext ;
    }
    cout<<'\n';
    return;
  }
  else
  {
    for(i=1;i<m-1;i++) //开始报数
    {
      p=p->pNext;
    } //找到报m-1的结点
    q=p->pNext; //q为报m的结点
    cout<<q->data<<"\t"; //输出报m的结点的值
    k=(q->pNext)->data; //k为下一个报数的起点
    p->pNext=q->pNext; //删除报m的结点
  }
}
cout<<p->data<<'\n'; //输出最后一个结点的值
}

原文地址:https://www.cnblogs.com/Ellfelo/p/josephuring.html