用循环队列解决约瑟夫环问题

问题描述

编号为1、2、…按顺时针坐在一张圆桌周围,每人持有一个密码,一个人选任意正整数为报数上限m,从第一个人开始报数报到m时停止报数,这个人出列,直到所有的人都出列,游戏结束。用线性表的内容来实现这个程序。

解决问题的步骤:

第一步:建立n个节点的无头循环链表。

第二步:从链表的第一个节点开始计数,直到寻找到第m个节点第三步:输出该节点的id值,并将其password值,作为新的m值。
第三步:输出该节点的id值,并将其passward值作为新的m的值。
第四步:根据新的m值,不断从链表中删除节点,直到循环链表为空,程序结束。

程序代码

#include<stdio.h>
#include<stdlib.h>
#define MAX 100

typedef struct NodeType        //自定义结构体类型
{
    int id;
    int password;
    struct NodeType *next;        //用于指向下一个结点的指针
}NodeType;

void CreatList(NodeType **, int);    //创建单向循环链表
NodeType *GetNode(int, int);        //得到一个结点
void PrintList(NodeType *);            //打印循环链表
int IsEmptyList(NodeType *);        //判空
void JosephusOperate(NodeType **, int);        //运行环求解

int main(void)
{
    int n = 0;
    int m = 0;
    NodeType *pHead = NULL;
    do
    {
        if (n>MAX)
        {
            printf("人数太多,请重新输入!\n");
        }
        printf("请输入人数n(最多%d个):", MAX);
        scanf("%d", &n);
    } while (n>MAX);
    printf("请输入初始密码m:");
    scanf("%d", &m);
    CreatList(&pHead, n);        //创建单向循环链表
    printf("\n----------打印循环链表---------\n");
    PrintList(pHead);        //打印链表
    printf("\n----------打印出队情况---------\n");
    JosephusOperate(&pHead, m);        //运行
    return 1;
}

void CreatList(NodeType **ppHead, int n)        //创建有n个结点的循环链表pphead 
{
    int i = 0;
    int iPassword = 0;
    NodeType *pNew = NULL;
    NodeType *pCur = NULL;
    for (i = 1; i <= n; i++)
    {
        printf("输入第%d个人的密码:",i);
        scanf("%d", &iPassword);
        pNew = GetNode(i, iPassword);
        if (*ppHead == NULL)
        {
            *ppHead = pCur = pNew;
            pCur->next = *ppHead;
        }
        else
        {
            pNew->next = pCur->next;
            pCur->next = pNew;
            pCur = pNew;
        }
    }
    printf("完成单向循环链表的创建!\n");
}

NodeType *GetNode(int iId, int iPassword)
{
    NodeType *pNew = NULL;
    pNew = (NodeType *)malloc(sizeof(NodeType));
    if (!pNew)
    {
        printf("Error, the memory is not enough!\n");
        exit(-1);
    }
    pNew->id = iId;
    pNew->password = iPassword;
    pNew->next = NULL;
    return pNew;
}

void PrintList(NodeType *pHead)
{
    NodeType *pCur = pHead;
    if (!IsEmptyList(pHead))
    {
        printf("--ID-- --PASSWORD--\n");
        do
        {
            printf("%3d %7d\n", pCur->id, pCur->password);
            pCur = pCur->next;
        } while (pCur!=pHead);
    }
}

int IsEmptyList(NodeType *pHead)
{
    if (!pHead)
    {
        printf("The list is empty!\n");
        return 1;
    }
    return 0;
}

void JosephusOperate(NodeType **ppHead, int iPassword)
{
    int iCounter = 0;
    int iFlag = 1;
    NodeType *pCur = NULL;
    NodeType *pPrv = NULL;
    NodeType *pDel = NULL;
    pPrv = pCur = *ppHead;
    while (pPrv->next != *ppHead)
    {
        pPrv = pPrv->next;
    }
    while (iFlag)
    {
        for (iCounter = 1; iCounter < iPassword; iCounter++)
        {
            pPrv = pCur;
            pCur = pCur->next;
        }
        if (pPrv==pCur)
        {
            iFlag = 0;
        }
        pDel = pCur;
        pPrv->next = pCur->next;
        pCur = pCur->next;
        iPassword = pDel->password;
        printf("第%d个人出列(密码:%d)\n", pDel->id, pDel->password);
        free(pDel);
    }
    *ppHead = NULL;
    getchar();
}
发布了19 篇原创文章 · 获赞 9 · 访问量 4563

猜你喜欢

转载自blog.csdn.net/qq_43777627/article/details/102594846