魔术师发牌问题

魔术师发牌问题


题目

  • 魔术师利用一副牌中的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();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值