美文网首页
2018-06-05 线性表3

2018-06-05 线性表3

作者: 多佳小昕 | 来源:发表于2018-06-05 21:21 被阅读0次

    十、 约瑟夫问题

    据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。
    然而Josephus和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。

    • 代码:
    //n个人围圈报数,报m出列,最后剩下的是几号?
    #include <stdio.h>
    #include <stdlib.h>
    typedef struct node
    {
        int data;
        struct node *next;
    }node;
    node *create(int n)
    {
        node *p = NULL, *head;
        head = (node*)malloc(sizeof (node ));
        p = head;
        node *s;
        int i = 1;
        if( 0 != n )
        {
            while( i <= n )
            {
                s = (node *)malloc(sizeof (node));
                s->data = i++;    // 为循环链表初始化,第一个结点为1,第二个结点为2。
                p->next = s;
                p = s;
            }
            s->next = head->next;
        }
        free(head);
        return s->next ;
    }
    int main()
    {
        int n = 41;
        int m = 3;
        int i;
        node *p = create(n);
        node *temp;
        m %= n;   // m在这里是等于2
        while (p != p->next )
        {
            for (i = 1; i < m-1; i++)
            {
                p = p->next ;
            }
            printf("%d->", p->next->data );
            temp = p->next ;                //删除第m个节点
            p->next = temp->next ;
            free(temp);
            p = p->next ;
        }
        printf("%d\n", p->data );
        return 0;
    }
    

    作业:编号为1~N的N个人按顺时针方向围坐一圈,每人持有一个密码(正整数,可以自由输入),开始人选一个正整数作为报数上限值M,从第一个人按顺时针方向自1开始顺序报数,报道M时停止报数。报M的人出列,将他的密码作为新的M值,从他顺时针方向上的下一个人开始从1报数,如此下去,直至所有人全部出列为止。

    #include <stdio.h>
    #include <stdlib.h>
    #define MAX_NODE_NUM 100
    #define TRUE 1U
    #define FALSE 0U
    
    typedef struct NodeType
    {
        int id;
        int cipher;
        struct NodeType *next;
    } NodeType;
    
    /* 创建单向循环链表 */
    static void CreaList(NodeType **, const int);
    /* 运行"约瑟夫环"问题 */
    static void StatGame(NodeType **, int);
    /* 打印循环链表 */
    static void PrntList(const NodeType *);
    /* 得到一个结点 */
    static NodeType *GetNode(const int, const int);
    /* 测试链表是否为空, 空为TRUE,非空为FALSE */
    static unsigned EmptyList(const NodeType *);
    
    int main(void)
    {
        int n, m;
        NodeType *pHead = NULL;
        while (1)
        {
            printf("请输入人数n(最多%d个): ", MAX_NODE_NUM);
            scanf("%d", &n);
            printf("和初始密码m: ");
            scanf("%d", &m);
            if (n > MAX_NODE_NUM)
            {
                printf("人数太多,请重新输入!\n");
                continue;
            }
            else
                break;
        }
        CreaList(&pHead, n);
        printf("\n------------ 循环链表原始打印 -------------\n");
        PrntList(pHead);
        printf("\n-------------删除出队情况打印 -------------\n");
        StatGame(&pHead, m);
    }
    
    static void CreaList(NodeType **ppHead, const int n)
    {
        int i, iCipher;
        NodeType *pNew, *pCur;
        for (i = 1; i <= n; i++)
        {
            printf("输入第%d个人的密码: ", i);
            scanf("%d", &iCipher);
            pNew = GetNode(i, iCipher);
            if (*ppHead == NULL)
            {
                *ppHead = pCur = pNew;
                pCur->next = *ppHead;
            }
            else
            {
                pNew->next = pCur->next;
                pCur->next = pNew;
                pCur = pNew;
            }
        }
        printf("完成单向循环链表的创建!\n");
    }
    
    static void StatGame(NodeType **ppHead, int iCipher)
    {
        int iCounter, iFlag = 1;
        NodeType *pPrv, *pCur, *pDel;
        pPrv = pCur = *ppHead;
        /* 将pPrv初始为指向尾结点,为删除作好准备 */
        while (pPrv->next != *ppHead)
            pPrv = pPrv->next;
        while (iFlag)
        {
            for (iCounter = 1; iCounter < iCipher; iCounter++)
            {
                pPrv = pCur;
                pCur = pCur->next;
            }
            if (pPrv == pCur)
                iFlag = 0;
            pDel = pCur; /* 删除pCur指向的结点,即有人出列 */
            pPrv->next = pCur->next;
            pCur = pCur->next;
            iCipher = pDel->cipher;
            printf("第%d个人出列, 密码: %d\n", pDel->id, pDel->cipher);
            free(pDel);
        }
        *ppHead = NULL;
        getchar();
    }
    
    static void PrntList(const NodeType *pHead)
    {
        const NodeType *pCur = pHead;
        if (EmptyList(pHead))
            return;
        do
        {
            printf("第%d个人, 密码: %d\n", pCur->id, pCur->cipher);
            pCur = pCur->next;
        }
        while (pCur != pHead);
        getchar();
    }
    
    static NodeType *GetNode(const int iId, const int iCipher)
    {
        NodeType *pNew;
        pNew = (NodeType *)malloc(sizeof(NodeType));
        if(!pNew)
        {
            printf("Error, the memory is not enough!\n");
            exit(-1);
        }
        pNew->id = iId;
        pNew->cipher = iCipher;
        pNew->next = NULL;
        return pNew;
    }
    
    static unsigned EmptyList(const NodeType *pHead)
    {
        if(!pHead)
        {
            printf("The list is empty!\n");
            return TRUE;
        }
        return FALSE;
    }
    
    

    相关文章

      网友评论

          本文标题:2018-06-05 线性表3

          本文链接:https://www.haomeiwen.com/subject/mynmsftx.html