约瑟夫环

  约瑟夫环,已知n个人,(编号从1、2、3、4......n),围在一张圆桌上,从编号为startnum的人开始报数,报到outnum的人出列,接着从下一个人开始从1报数,数到outnum的人又出列;依次规律重复下去,知道所有人全部出列,请写出出列的依次序号数。

  这是一个约瑟夫环问题,用单链表来做,具体地:

  1.建立一个无头结点的循环链表,依次编号1、2、3、4......n;

  2.将临时首个指针p移动到开始报数的人的位置,以前保存该位置的前驱节点r->next=p(为了方便删除p);

  3.开始报数,同时p和r向后移动,当报到outnum时,将p点删除,然后p重新赋值后面一个节点,r跟上;

  4.若所有节点删除完毕,停止;否则继续执行第3部。

具体代码如下:

  

#include<iostream>
using namespace std;

struct Node 
{
    int data ;
    Node *next;
};
//约瑟夫环儿的问题,一共len 个人  从第startnum个人开始报数 
//数到outnum的人出列 求 出列序号是什么
void josephus(int Len,int startnum,int outnum)
{
    Node *head=(Node*)malloc(sizeof(Node));
    if (head==NULL)//判断内存是否申请成功
    {
        return ;
    }
    head->next=NULL;
    head->data=1;
    Node *curr=head;//建立循环链表的时候的临时指针
    for (int i=2;i<=Len;i++)
    {
        Node* pNew = (Node*)malloc(sizeof(Node));
        pNew->data=i;
        curr->next=pNew;
        curr=pNew;
    }
    curr->next=head;//尾节点后继为头指针,构成循环链表
    
    Node *p=head;//删除节点时用的当前指针
    Node *r=curr;//r始终是p的前驱
    while(--startnum)//将p移动到开始数的位置startnum
    {
        r=p;
        p=p->next;
    }
    
    while (Len--)
    {
        for ( int num=outnum;--num;r=p,p=p->next);//寻找要删除的位置
        r->next=p->next;//将删除位置的后继位置赋值给前驱的后继指针
        cout<<p->data<<" ";//打印删除节点序号
        free(p);
        p=r->next;//将p重新赋值为第一个报数的人
    }
    
}
void main()
{
    josephus(12,1,2);
}

执行结果如下图:

  

原文地址:https://www.cnblogs.com/mu-tou-man/p/3931762.html