魔术师发牌问题,魔术师拿出13张黑桃扑克牌表演魔术,对底下观众讲道,我只要数数就知道这张牌是什么,然后数到1翻出来第一张A,并将A拿出来放到桌子上,用剩下的牌,重新数,数到2拿出来第2张牌...以此内推,求魔术师用怎样的牌序才能达到此目的。
首先分析问题,我们可以得到一个大致的类似链表牌序为
1【】2【】【】3【】【】【】4【】【】【】。所以规律也很明显了,于是我们就可以得到第二次的链表整个循环的结果
1【】2【5】【】3【】【】【】4【】【6】【】.
所以用循环链表解决问题,它的算法应该是
for(int i =0;i<counter;i++)
{
target=target->next
}
if(target->data==0){
target=counter;
counter++;}
仔细想一下这是不是有什么问题,没错因为我们的牌有些是被放在了桌子上,所以我们在循环到这些牌的时候要跳过。
于是改进后的算法
for(int i=1;i<counter;i++)
{
target=target->next;
//遇到被放到桌子上的牌就多循环一次指向下一位
if(target->data!=0
{
i - -;
}
}
所以核心的算法其实就这么简单,然后就是具体的实现了,下面贴代码:
#include<stdio.h>
#include<stdlib.h>
typedef struct Node
{
int data;
struct Node* next;
}Node;
Node *create()
{
Node *head = (Node*)malloc(sizeof(Node));
Node *target = NULL;
target = head;
for (int i = 1; i < 13; i++)
{
Node *temp = (Node*)malloc(sizeof(Node));
temp->data = 0;
target->next = temp;
target = temp;
}
target->next = head;
return head;
}
void margiccard(Node *head)
{
Node *target = head;
int count = 2;
target->data = 1;
while (1)
{
for (int j = 0; j < count; j++)
{
target = target->next;
if (target->data != 0)
{
j--;
}
}
if (target->data == 0)
{
target->data = count;
count++;
if (count == 14)
break;
}
}
}
void main()
{
Node* list=NULL;
list = create();
Node* head = list;
margiccard(list);
for (int i = 1; i <= 13; i++)
{
printf("黑桃%d", list->data);
list = list->next;
}
}