魔术师发牌和拉丁方阵
本文利用经典的魔术师发牌问题与拉丁法阵分别解说了循环链表与单向链表的使用,作为算法中的经典,对于链表的学习和理解都有着非常大的帮助,最好还是一看。
魔术师发牌问题
问题描写叙述:
魔术师利用一副牌中的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; }