Fork me on GitHub

算法之美--4.3.4 魔术师发牌问题

 问题描写叙述:

       魔术师手中有A、2、3……J、Q、K十三张黑桃扑克牌。在表演魔术前,魔术师已经将他们依照一定的顺序叠放好(有花色的一面朝下)。魔术表演过程为:一開始,魔术师数1,然后把最上面的那张牌翻过来,是黑桃A;然后将其放到桌面上;第二次,魔术师数1、2;将第一张牌放到这些牌的最以下,将第二张牌翻转过来,正好是黑桃2;第三次,魔术师数1、2、3;将第1、2张牌依次放到这些牌的最以下,将第三张牌翻过来正好是黑桃3;……直到将全部的牌都翻出来为止。问原来牌的顺序是怎样的。

/*!
 * \file 算法之美--4.3.4 魔术师发牌问题.cpp
 * \date 2017/02/25 15:58
 *
 * \author ranjiewen
 *
 * \brief 问题描写叙述:
             魔术师手中有A、2、3……J、Q、K十三张黑桃扑克牌。在表演魔术前,魔术师已经将他们依照一定的顺序叠放好(有花色的一面朝下)。
             魔术表演过程为:一開始,魔术师数1,然后把最上面的那张牌翻过来,是黑桃A;然后将其放到桌面上;第二次,魔术师数1、2;
             将第一张牌放到这些牌的最以下,将第二张牌翻转过来,正好是黑桃2;第三次,魔术师数1、2、3;将第1、2张牌依次放到这些牌的最以下,将第三张牌翻过来正好是黑桃3;
             ……直到将全部的牌都翻出来为止。问原来牌的顺序是怎样的。
 *
 * TODO: long description
 *
 * \note
*/

#include <iostream>
using namespace std;

#define N 13

typedef struct Node
{
    int data;
    Node* pNext;
    Node(int data_ = 0, Node* pNext_ = nullptr) :data(data_), pNext(pNext_){}
}Node,*LinkList;




void InitLinkList(LinkList&L,int n) //创建并初始化循环链表,L表示表头节点,n创建节点元素的个数
{
    L = (Node*)malloc(sizeof(Node));
    L->pNext = L; //头结点循环
    LinkList p;
    for (int j = 0; j < n; j++)  //一直在头结点插入
    {
        p = (Node*)malloc(sizeof(Node));
        p->data = 0;
        p->pNext = L->pNext;//插入节点指向头结点
        L->pNext = p; //头结点指向新的节点
    }
    return;
}

void Magician(LinkList& L, int n) //魔术师问题求解
{
    LinkList p = L->pNext;
    p->data = 1;//第一张为1;
    for (int num = 2; num <= n;num++) //依次找到2-n牌的位置
    {
        int i = 0;
        while (i<num)
        {
            p = p->pNext;
            if (p->data==0) //跳过有牌的位置,没有牌的才加1
            {
                i++;
            }
        }
        p->data = num;
    }
}

void Print(LinkList&L)
{
    LinkList p = L->pNext;
    cout << "Print:";
    while (p!=L)
    {
        cout << p->data << " ";
        p = p->pNext;
    }
    cout << endl;
}

int main()
{
    LinkList L;
    InitLinkList(L,N);
    Magician(L,N);
    Print(L);
    return 0;
}

通过约瑟夫环和魔术师发牌问题:对基本的链表操作熟悉下了,特别是创建过程,对于循环链表;循环的方式可以把头结点放在里面(本题),也可以不放在里面(约瑟夫问题),通过内存可以查看;两种方式判断循环结束的方式也有差别。

CirSinglist *p;
p = pHead->pNext;
while (p->pNext!=p)  (不带头结点)

LinkList p = L->pNext;
cout << "Print:";
while (p!=L)(带头结点)

 

魔术师发牌问题

c语言魔术师发牌问题(循环链表)

 

 

posted @ 2017-02-24 18:05  ranjiewen  阅读(2413)  评论(0编辑  收藏  举报