问题描述:魔术师利用一副牌中的13张黑牌,预先将他们排好后叠放在一起,牌面朝下。对观众说:“我不看牌,只数数就可以猜到每张牌是什么,我大声数数,你们听,不信?现场演示。魔术师将最上面的那张牌数为1,把他翻过来正好是黑桃A,将黑桃A放在桌子上,第二次数1,2,将第一张牌放在这些牌的下面,将第二张牌翻过来,正好是黑桃2,也将它放在桌子上这样依次进行将13张牌全部翻出,准确无误。
问题:牌的开始顺序是如何安排的?
思路:创建循环链表的时候将每个节点的data都置为0;然后在发牌顺序函数中输入值的时候,设置一个变量CountNumber,这是循环次数,因为当牌为2时,就是去掉已经有值的节点外的第二个节点,在循环中可能会遇到节点中已经有值的情况,此时就要增加一次循环次数,所以j--;
//魔术师发牌问题 #include <stdio.h> #include <stdlib.h> #define CardNumber 13 typedef struct Node{ int data; struct Node*Next; }Node; Node* CreateLinkList(){ Node *temp; Node *target; Node *head=NULL; int i; head=(Node*)malloc(sizeof(Node)); target=head; for(i=0;i<CardNumber;i++){ temp=(Node*)malloc(sizeof(Node)); temp->data=0; target->Next=temp; target=temp; } target->Next=head->Next; free(head); return target->Next; } //发牌顺序 void magician(Node*head){ Node *p=head; int j; p->data=1; int CountNumber=2; while(1){ for(j=0;j<CountNumber;j++){ p=p->Next; if(p->data!=0){ j--;//增加一次循环次数 } } p->data=CountNumber++; if(CountNumber==14) break; } } int main(){ Node*p; int i; p=CreateLinkList(); magician(p); for(i=0;i<CardNumber;i++){ printf("黑桃%d ",p->data); p=p->Next; } }
拉丁方阵问题;
拉丁方阵是一种n×n的方阵,方阵中恰有n种不同的元素,每种元素恰有n个,并且每种元素在一行和一列中恰好出现一次。著名数学家和物理学家欧拉使用拉丁字母来作为拉丁方阵里元素的符号
拉T方阵因此而得名。
思路:创建有n个节点的循环链表,然后将1-n的值分别存到n个节点当中,然后在输出的时候在内层循环中多加一层循环;
//魔术师发牌问题 #include <stdio.h> #include <stdlib.h> typedef struct Node{ int data; struct Node*Next; }Node; Node* CreateLinkList(int n){ Node *temp; Node *target; Node *head=NULL; int i; head=(Node*)malloc(sizeof(Node)); target=head; for(i=1;i<=n;i++){ temp=(Node*)malloc(sizeof(Node)); temp->data=i; target->Next=temp; target=temp; } target->Next=head->Next; free(head); return target->Next; } int main(){ Node*p,*q; int j,i,n; scanf("%d",&n); p=CreateLinkList(n); q=p; for(i=0;i<n;i++){ p=q; for(j=0;j<i;j++) p=p->Next; for(j=0;j<n;j++){ printf("%d ",p->data); p=p->Next; } printf("\n"); } }