约瑟夫问题

设编号分别为:1,2,...,n的n个人围坐一圈。约定序号为k(1 <= k < = n)的人从1开始计数,数到m的那个人出列,他的下一位又从1开始计数,数到m的那个人又出列,依次类推,直到所有人出列为止。

 

#include <stdio.h>
#include <stdlib.h>
//思路:用循环链表实现
typedef struct node
{
    int data;
    struct node *next; //不要忘记struct
}node;
//第一步:先建立带头结点的环形链表模拟人围成的环,返回第一个结点的指针
node* create(int n)
{
    node *p,*head; //p指针为位移标记指针,head指针为头指针
    head = (node*)malloc(sizeof(node));//生成头结点
    p = head; //p指针指向头结点
    node *s;
    int i;
    for(i=1; i<=n; i++)
    {
        s = (node*)malloc(sizeof(node));//生成新结点
        s->data = i; //s结点的data域存放序号
        p->next = s;//p的next域指针指向下一个结点
        p = s; //p指针位移指向下一个结点
    }

    s->next = head ->next; //最后一个结点的next域指向第一个结:形成环
    free(head);
    return s->next; //返回第一个结点的指针
}
int main()
{
    int n,m;//一共n个人 数到m的人出局
    scanf("%d %d",&n,&m);
    node *p;
    p = create(n);  //指向第一个结点的指针

    //第二步:数到m的人出局
    int i,a;
    node *temp;
    a=n%m;//每次都数3个数即m=3  所以对3取余
    while(p!=p->next)
    {
        for(i=1; i<a; i++)
        {
            p=p->next;//运动指针:指向待删除结点的前一个结点!
        }
        temp=p->next; //temp指针为待删除位置!
        printf("%d->",temp->data);//输出删除的结点data值
        p->next = temp->next;//如果m=3则第二结点next域指向第四个位置
        p = temp->next;//p指向下一个首结点
    }
    printf("%d",p->data);
    return 0;
}

 

posted @ 2017-02-23 13:31  清风追梦enjoy  阅读(184)  评论(0编辑  收藏  举报