魔术师发牌和拉丁方阵

本文利用经典的魔术师发牌问题与拉丁法阵分别讲解了循环链表与单向链表的使用,作为算法中的经典,对于链表的学习和理解都有着很大的帮助,不妨一看。


魔术师发牌问题

问题描述:

魔术师利用一副牌中的13张黑牌,预先将他们排好后叠放在一起,牌面朝下。对观众说:“我不看牌,只数数就可以猜到每张牌是什么,我大声数数,你们听,不信?现场演示。”魔术师将最上面的那张牌数为1,把他翻过来正好是黑桃A,将黑桃A放在桌子上,第二次数1,2,将第一张牌放在这些牌的下面,将第二张牌翻过来,正好是黑桃2,也将它放在桌子上这样依次进行将13张牌全部翻出,准确无误。

问题:牌的开始顺序是如何安排的?

经典循环链表问题,代码如下:

#include<iostream>
using namespace std;
#define CardNumber 13
struct node
{
	int data;
	struct node *next;
}*linklist;
void CreateLinkList()
{
	linklist = NULL;
	node *p,*q;
	int i;
	p=linklist;
	for(i=0;i<CardNumber;i++)
	{
		p=new node;
		p->data=0;
		if(linklist==NULL)
			linklist=p;
		else
			q->next=p;
		q=p;
	}
		q->next=linklist;
}
void Magician()
{
	node *p=linklist;
	int j;
	int count=2;
	p->data=1;
	while(1)
	{
		for(j=0;j<count;j++)
		{
			p=p->next;
			if(p->data!=0)
			{
				j--;
			}
			
		}
		if(p->data==0)
		{
			p->data=count;
			count++;
			if(count==14)break;
		}		
	}
}
void print()
{
	node *p=linklist;
	while(p->next!=linklist)
	{
		cout<<p->data<<endl;
		p=p->next;
	}
		cout<<p->data<<endl;
}
int main()
{
	CreateLinkList();
	Magician();
	print();
	return 0;
}

拉丁方阵问题

 问题描述:

拉丁方阵是一种n×n的方阵,方阵中恰有n种不同的元素,每种元素恰有n个,并且每种元素在一行和一列中 恰好出现一次。

著名数学家和物理学家欧拉使用拉丁字母来作为拉丁方阵里元素的符号,拉丁方阵因此而得名。

例如:

1      2      3

2      3      1

3      1      2

问题:如何构造N阶拉丁方阵?普通代码如下:(N阶所有拉丁方阵)

#include<iostream>
using namespace std;
#define N 3 /*确定N值*/
int main()
{
	int i,j,k,t;
	printf("The possble Latin Squares of order %d are:\n",N);
	for(j=0;j<N;j++) /*构造N个不同的拉丁方阵*/
	{
		for(i=0;i<N;i++)
		{
			t=(i+j)%N; /*确定该拉丁方阵第i 行的第一个元素的值*/
			for(k=0;k<N;k++) /*按照环的形式输出该行中的各个元素*/
				cout<<(k+t)%N+1;
			cout<<endl;
		}
		printf("\n");
	}
}

单链表实现代码:(拉丁方阵的标准型,其它类型可用类似的单链表方法得到)

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

typedef struct node
{
        int data;
        struct node *next;
}linklist;

linklist *CreateList(int n);


//创建链表
linklist *CreateList(int n)
{
        linklist *head, *s, *r;
        head = NULL;
        r = head;
        
        for (int i = 1; i <= n; i++)
        {
                s = (linklist *)malloc(sizeof(node));
                s->data = i;
                if (head == NULL)
                        head = s;
                else
                        r->next = s;
                r = s;
        }
        r->next = head;

        return head; 
}

int main()
{
        linklist *L,*head;
        int n; 
        printf("请输入拉丁方阵的阶数n:");
        scanf("%d", &n);
        L = CreateList(n);
        head = L;
        for (int i = 1; i <= n; i++)
        {
                L = head;
                for (int j = 1; j < i; j++)
                {
                        L = L->next;
                }
                for (int k = 1; k <= n && L->next != NULL; k++)
                {
                        printf("%4d", L->data);
                        L = L->next;
                }
                printf("\n");
        }

        return 0;
}


  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值