实习题-约瑟夫环问题(二)

来源:互联网 发布:手机淘宝怎么退款申请 编辑:程序博客网 时间:2024/05/16 07:19
 //该程序演示用环型动态链表实现约瑟夫问题解答
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
    int number; //人员的编号
    int mima; //该人的密码
    struct node * next; //下一人结点的地址(指针)
}Node, *Link;

//初始化带头结点的环型链表
Link Init(void)
{
    Link L;
    L = (Link)malloc(sizeof(Node));
    L->next = L;
    return L;
}
//在头结点的前面插入一个结点
void Insert(Link L, int e_mima, int e_number)
{
    Link p,q;
    p = (Link)malloc(sizeof(Node));
    p->mima = e_mima;
    p->number = e_number;
    q = L;
    while(q->next != L)q = q->next; //让q指向最后的一个结点
    p->next = q->next;
    q->next = p;
}
//删除编号为 i 的结点
void Delete(Link L, int i)
{
    Link p,q;
    q = L;
    while(q->next != q && q->next->number != i)
        q = q->next;
    if(q->next->number == i)
    {
        p = q->next;
        q->next = p->next;
        free(p);
    }
}
void main()
{
    Link p,q,L;
    int i,m,n,mima;
    printf("请输入人数和初始密码:");
    scanf("%d%d",&n,&m);
    if(n<=0 || m<=0)return;
    L = Init();
    i=1;
    while(i<=n)
    {
        printf("请输入第 %d 个人的密码:",i);
        scanf("%d",&mima);
        if(mima <= 0)continue;
            Insert(L, mima, i); //向循环链表中加入结点
        i++;
    }
    i = 1;
    p = L->next;
    while(L->next != L) //当循环链表不为空则循环
    {
        q = p;
        p = p->next;
        if(p ==L) //若p指向头结点,则跳过
        {
            q = p;
            p = p->next;
        }
        i++;
        if(i == m) //若i为密码值,则p所指结点要删除
        {
            printf("%d\t",p->number);
            m = p->mima; //获取新的密码
            Delete(L, p->number); //删除要出列的人的结点
            p = q;
            i = 0; //i复位到零,重新计数
        }
    }
}