算法之美--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語言魔術師發牌問題(循環鏈表)

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM