【数据结构】求解魔术师发牌问题

【数据结构】求解魔术师发牌问题

题目描述
魔术师发牌问题的简介:一位魔术师掏出一叠扑克牌,魔术师取出其中13张黑桃,洗好后,把牌面朝下。说:“我不看牌,只数一数就能知道每张牌是什么?”魔术师口中念一,将第一张牌翻过来看正好是A;魔术师将黑桃A放到桌上,继续数手里的余牌,第二次数1,2,将第一张牌放到这叠牌的下面,将第二张牌翻开,正好是黑桃2,也把它放在桌子上。第三次数1,2,3,前面二张牌放到这叠牌的下面,取出第三张牌,正好是黑桃3,这样依次将13张牌翻出,全部都准确无误。求解:魔术师手中牌的原始顺序是什么样子的?


题目分析
从题目中我们可以看到,魔术师发牌的时候并不是连续发的,而是每次都隔着一定的步长,且步长递增,那么我们要做的就是按照他发牌的顺序来求解每一张牌,即先给第一张牌赋值1 , 然后数1 , 2给第3张牌赋值2,然后数1 , 2 ,3 给第6张牌赋值3…依此类推,并且因为中间间隔的牌还没赋值,所以我们赋值到末尾的时候还要从头开始继续赋值,所以我们可以采用循环链表来进行问题的求解。


#include <stdio.h>
#include <stdlib.h>

//牌数为13张 
#define Number 13			

//定义结点 
typedef struct Node
{
		int data;				 
		struct Node *next;
} node;

//初始化循环链表
node* createlist()
{
		node *head = NULL, *tail , *temp;
				
		tail = head;
		
		for(int i = 1 ; i <= Number ; i++)
		{
				temp = (node *)malloc(sizeof(node));
				if(temp == NULL)		//内存申请不成功时返回错误信息 
						exit(0);
						
				temp->data = 0;				//将每张牌的值初始化为0,后续如果牌面为0说名还没赋值 
				
				if(head == NULL)
						head = temp;
				else
						tail->next = temp;
						
				tail = temp;				//更新尾指针 
		}
		tail->next = head;					//记得要链接起来,形成循环链表 
		return head;
}
 
void magic(node **head)
{
		node *p;						//p指针用于临时存放每次新的赋值 , 即用来遍历循环链表 
		p = *head;
		p->data = 1;					//第一张牌赋值为1 
		int countnumber = 2;		//countnumber是每次的步数
		
		while(1)
		{
				//定位要赋值的牌的位置 
				for (int i = 1 ; i <= countnumber ; i++)
				{
						p = p->next;				//往下遍历 
						if(p->data != 0)			//如果这张牌赋值过了就跳过 
								--i;				//本次计的步长不算 
				}
				
				p->data = countnumber;				//找到位置后赋值 
				countnumber++;
				if(14 == countnumber)
						break;
		}
}

int main(void)
{
		node *head , *current;
		head = createlist();
		magic(&head);
		
		current = head;
		
		for(int i = 1 ; i <= Number ; i++)
		{
				printf("黑桃%d " , current->data);
				current = current->next;
		}
	
		return 0;
}

OK!运行得到结果,验证一下没有错误。

黑桃1 黑桃8 黑桃2 黑桃5 黑桃10 黑桃3 黑桃12 黑桃11 黑桃9 黑桃4 黑桃7 黑桃6 黑桃13
--------------------------------
Process exited after 0.03923 seconds with return value 0
请按任意键继续. . .
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端corner

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值