魔术师发牌问题
题目:
- 魔术师利用一副牌中的13张黑牌,预先将它们排好后叠放在一起,牌面朝下。对观众说:“我不看牌,只数数就可以猜到每张牌是什么,我大声数,你们听,不信?现场演示。”魔术师将最上面的那张牌数为1,把他翻过来正好是黑桃A1,将黑桃A放在桌子上,第二次数1,2,将第一张牌放在这些牌的下面,将第二张牌翻过来,正好是黑桃2,也将它放在桌子上这样依次进行将13张牌全部翻出,准确无误。
问题:牌的开始顺序是如何安排的?
问题分析:用循环链表来做,首先将扑克牌按原顺序初始化好,接下确定魔术师魔术时牌的顺序,即下面的顺序:

代码中用函数showPoker()实现,为了方便创建虚拟头结点和指针p,指针p遍历从虚头开始遍历链表,p指针随双for循环很容易找到元素的新位置,当p指针处结点有元素,不计数,因为要保证每个元素之间各自的间隔,例如1和2间隔一个位置,2和3间隔两个位置

最后在每次p指针移动完对应次数后,给p指针处结点数据域对应值,结束后打印链表顺序对比,测试代码的正确性。
代码实现(Java):
package DS02.动态链表;
public class MagicPoker {
private Node head;
private Node rear;
private int size;
//构造函数 初始化
public MagicPoker(){ //先把十三个点弄出来
head=new Node(); //第一个结点,即A位置
rear=head;
rear.next=head;
for(int i=2;i<=13;i++){ //加后12个结点
Node n=new Node();
n.next=rear.next; //尾插法,加结点
rear.next=n;
rear=rear.next;
} //此时,扑克是按着大小顺序排列的
size=13;
}
//显示扑克牌新的顺序,
public void showPoker(){
Node virtualHead=new Node(); //先创建一个虚拟头结点
virtualHead.next=virtualHead; //头结点指针域指向头结点地址 构成循环链表.
Node p=virtualHead;
for(int i=1;i<=13;i++){
for(int j=0;j<i;){
if(p.next.number==0){
p=p.next;
j++;
}else{
p=p.next;
}
}
p.number=i;
}
p=virtualHead;
for(int i=1;i<=13;i++){
p=p.next;
System.out.print(p.number+" ");
}
}
//结点内部类
private class Node{
int number;
Node next;
public Node(){}
public Node(int number,Node next){
this.number=number;
this.next=next;
}
}
public static void main(String[] args) {
MagicPoker mp=new MagicPoker();
mp.showPoker();
}
}
1558

被折叠的 条评论
为什么被折叠?



