C语言数据结构之用循环链表解决魔术师发牌问题

问题描述:

  • 魔术师利用一副牌中的13张黑桃牌,预先将他们排好后叠放在一起,牌面朝下。对观众说:“我不看牌,只数数就可以猜到每张牌是什么,我大声数数,你们听,不信?现场演示。”魔术师将牌堆最上面的哪张排数为1,把他翻过来正好是黑桃A,将黑桃A从牌堆抽出放在桌子上,第二次数1、2,将第一张放在牌堆最下面,第二张翻开,正好是黑桃2,也将它抽出放在桌子上。这样依次进行将13将牌全部翻出,准确无误。问牌最开始的顺序是怎样排的
    简单点说:把13张牌按照一定的顺序排好,然后依次取牌,将每次取到的牌放在最下面,情形如下:
    数一次,取牌,黑桃1,放牌堆最下面
    数两次,取牌,黑桃2,放牌堆最下面
    数三次,取牌,黑桃3,放牌堆最下面
    数四次,取牌,黑桃4,放牌堆最下面
    …直到取到最后的黑桃13(黑桃K),表演结束!

通过问题我们可以发现这是典型的约瑟夫问题的逆运算,因此我们可以用循环链表来解决。

思路:用循环链表模拟魔术师取出牌的过程,最后从头到位输出即可。

 1 0 0 0 0 0 0 0 0 0 0 0 0

 1 0 2 0 0 0 0 0 0 0 0 0 0

 1 0 2 0 0 3 0 0 0 0 0 0 0

 1 0 2 0 0 3 0 0 0 4 0 0 0

 1 0 2 5 0 3 0 0 0 4 0 0 0

 1 0 2 5 0 3 0 0 0 4 0 6 0

 1 0 2 5 0 3 0 0 0 4 7 6 0

 1 8 2 5 0 3 0 0 0 4 7 6 0

 1 8 2 5 0 3 0 0 9 4 7 6 0

 1 8 2 5 10 3 0 0 9 4 7 6 0

 1 8 2 5 10 3 0 11 9 4 7 6 0

 1 8 2 5 10 3 12 11 9 4 7 6 0

 1 8 2 5 10 3 12 11 9 4 7 6 13

 1 8 2 5 10 3 12 11 9 4 7 6 13

代码:

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

typedef struct node{
    int id;
    struct node * next;
}Node,*LinkList;

void addNode(LinkList * linkList,int id);
void traverse(LinkList * linkList,void (*pfun)(int));
void initLinkList(LinkList * linkList);


void pfun(int data)
;

int main(void)
{
    LinkList linkList = NULL;
    initLinkList(&linkList);
    int i,k;
    for(i=0;i<13;i++)
        addNode(&linkList,0);//生成13个节点并将值初始化为0
    Node * pn = linkList;
    Node * temp;

    for(i=0;i<13;i++)
    {
        k = 0;
        while(k<i+1)
        {
            pn = pn->next;
            if(pn->id == 0 && pn != linkList)
            {
                k++;
            }
        }

        pn->id = i+1;


        traverse(&linkList,pfun);
        printf("\n");
    }

    traverse(&linkList,pfun);
    pn = linkList;

    while(pn->next != linkList)
    {
        temp = pn->next;
        pn = pn->next;
        free(temp);
    }

    free(linkList);

    return 0;
}


void pfun(int data)
{
    printf(" %d",data);
}
void initLinkList(LinkList * linkList)
{
    (*linkList) = (Node *)malloc(sizeof(Node));
    (*linkList)->next = *linkList;
}

//头插法添加元素
void addNode(LinkList * linkList,int id)
{
    Node * pn = (Node *)malloc(sizeof(Node));
    pn->id = id;

    if(!(*linkList)->next)
    {
        pn->next = *linkList;
    }else{
        pn->next = (*linkList)->next;
    }
    (*linkList)->next = pn;
}

void traverse(LinkList * linkList,void (*pfun)(int))
{
    Node * pn = (*linkList);

    while(pn->next != *linkList)
    {
        pfun(pn->next->id);
        pn = pn->next;
    }
}

代码运行结果:《C语言数据结构之用循环链表解决魔术师发牌问题》

    原文作者:魔术师发牌问题
    原文地址: https://blog.csdn.net/a1135004584/article/details/79330919
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞