约瑟夫环问题(Josephus问题)链表实现

描述
设有N名同学手拉手围成一圈,自1、2、3、......开始编号,现从1号开始连续数数,
每数到M将此同学从圈中拉走, 求最后被拉走的同学的编号
 
输入
两个正整数,分别为N和M。0<N<=100 ;0<M<65535
 
输出
一个正整数,为最后被拉走的同学的编号,最后输出回车
 
输入样例
5 3
 
输出样例
4

1.单循环链表实现

#include<stdio.h>
#include<stdlib.h>

typedef struct node
{
    int data;
    struct node *next;
}LinkNode,*LinkList;

LinkList Create(int n)
{
    LinkNode *p,*q;
    int i;
    q = (LinkNode *)malloc(sizeof(LinkNode));
    p = q;
    q->data = 1;
    q->next = q;
    for(i = 2;i <= n;i++)
    {
        p = (p->next = (LinkNode *)malloc(sizeof(LinkNode)));
        p->data = i;
        p->next = q;
    }
    return p;
}
void Josephus(LinkList head,int m)
{
    while(head != head->next)
    {
        for(int i = 1;i < m;i++)
        {
            head = head->next;
        }
        head->next = head->next->next;
    }
    printf("%d\n",head->data);
}
int main()
{
    int n,m;
    scanf("%d %d",&n,&m);
    LinkList head;
    head = Create(n);
    Josephus(head,m);
    return 0;
}

2.双向循环链表实现

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

typedef struct node
{
    int data;
    struct node *next;
    struct node *prior;
}DoubleNode,*DoubleList;

DoubleList Create(int n)
{
    DoubleList head = NULL;
    DoubleNode *p,*q;
    int i;
    for(i = 1;i <= n;i++)
    {
        p = (DoubleNode *)malloc(sizeof(DoubleNode));
        if(p == NULL)
        {
            printf("动态内存分配失败!\n");
            exit(-1);
        }
        p->data = i;
        p->next = NULL;
        if(head == NULL)
        {
            head = p;
            p->prior = head;
            p->next = head;
        }
        else
        {
            p->next = q->next;
            q->next = p;
            p->prior = q;
            head->prior = p;
        }
        q = p;
    }
    return head;
}

void Josephus(DoubleList head,int n,int m)
{
    int i;
    DoubleNode *p,*q;
    p = head;
    while(p->next != p)
    {
        for(i = 1;i < m;i++)
        {
            q = p;
            p = p->next;
        }
        q->next = p->next;
        p->next->prior = q;
        printf("%d ",p->data);
        free(p);
        p = q->next;
    }
    printf("%d\n",p->data);
    free(p);
    return;
}
int main()
{
    DoubleList Head;
    int n, k, m;
    //printf("输入玩家个数 n = ");
    scanf("%d", &n);
    //printf("报数为 m 的人出列 m = ");
    scanf("%d", &m);
    Head = Create(n);
    Josephus(Head, n, m);
    return 0;
}

我个人觉得单循环链表更好用些~

猜你喜欢

转载自blog.csdn.net/zhao2018/article/details/80602791