JAVA使用双向循环链表-实现约瑟夫问题

前奏
链表的特点:各个相依节点的地址空间不一定是连续的,这样就充分了历用了内存中的碎片内容存
约束夫小述
Josephus有过的故事:39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓。
于是决定了自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀。
然后下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从,
Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏
双向链表代码(不带头结点)
//创建一个双向链表类
class DoubleLinked {

    
    //创建一个头节点
    DoubleLinkedNode headNode=new DoubleLinkedNode(null);

    public void showNode(){
        //获取头节点
        DoubleLinkedNode currNode=headNode;
        while(currNode.nextNode!=null){
            System.out.println(currNode.nextNode.currData+"====向上"+currNode.nextNode.preNode.currData+"===向下"+currNode.nextNode.nextNode.currData);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            currNode=currNode.nextNode;
        }
    }
    
    //实现双向循环链表
    public void addNodeOrderBy(Object value){
        //获取对应的头节点信息
        DoubleLinkedNode currNode=headNode;

        //创建一个临时遍历存储当前节点的下一个相依节点信息
        DoubleLinkedNode temp=null;

        //将当前添加的信息封装到一个节点中
        DoubleLinkedNode newNode=new DoubleLinkedNode(value);

        //循环判断整个链表
        while(currNode.nextNode!=null){
            //获取当前节点的下一个相依节点
            temp=currNode.nextNode;
            if((Integer)temp.currData>(Integer) value){

                break;
            }
            //更新当前节点信息
            currNode=temp;
            //判断当前循环链表节点是否 在最后一个如果是最后一个跳出当前循环
            if(currNode.nextNode==headNode.nextNode){
                break;
            }
        }

        //判断当前链表为空怎么处理
        if(currNode.nextNode==null){
            //更新新节点的上下相依节点
            newNode.preNode=newNode;
            newNode.nextNode=newNode;
            //将当前新节点赋值给 当前节点向下相依节点上
            currNode.nextNode=newNode;
        }
        //当新添加的节点在整个链表最前一个怎么处理
        else if(currNode==headNode){

            //获取最后一个节点信息
            DoubleLinkedNode lastNode=headNode;
            while(lastNode.nextNode!=null){
                //更新当前节点信息
                lastNode=lastNode.nextNode;
                if(lastNode.nextNode==headNode.nextNode){
                    break;
                }
            }
            //更新新节点的上下相依节点位置
            newNode.preNode=lastNode;
            newNode.nextNode=currNode.nextNode;
            //更新当前节点向下相依节点的向上相依节点信息
            currNode.nextNode.preNode=newNode;
            //将更新当前向下相依节点信息
            currNode.nextNode=newNode;
            //更新末尾节点向下相依节点信息
            lastNode.nextNode=newNode;
        }

        //当前添加的节点在整个链表最后一个怎么处理
        else if(currNode.nextNode==headNode.nextNode){
            //更新新节点的上下相依节点
            newNode.preNode=currNode;
            newNode.nextNode=currNode.nextNode;
            //更新当前节点向下相依节点
            currNode.nextNode=newNode;
            headNode.nextNode.preNode=newNode;
        }
        //当新添加的节点在整个链表的中间怎么处理
        else{
            //更新新节点的上下相依节点信息
            newNode.preNode=currNode;
            newNode.nextNode=currNode.nextNode;
            currNode.nextNode.preNode=newNode;
            currNode.nextNode=newNode;
        }
    }
}
//创建一个双向链表节点类
class DoubleLinkedNode{
    public DoubleLinkedNode preNode;
    public DoubleLinkedNode nextNode;
    public Object currData;
    public DoubleLinkedNode(Object data){
        this.currData=data;
    }
}

约瑟夫代码实现(配合双向循环链表)

//实现约瑟夫问题

//Josephus有过的故事:39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓。
//于是决定了自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀。
//然后下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从,
//Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏
public class PracticeJoseph {

    public static void main(String[] args) {

        int numberCount=0;
        int number=41;
        //使用双向循环排序链表的
        DoubleLinked link=new DoubleLinked();
        for(int index=1;index<=number;index++){
            link.addNodeOrderBy(index);
        }


        //获取当前链表头节点信息
        DoubleLinkedNode currNode=link.headNode;
        while(currNode.nextNode!=null){
            DoubleLinkedNode temp=currNode.nextNode;
            numberCount++;

            if(numberCount==3){
                if(number--<3){
                    break;
                }
                System.out.println(temp.currData);

                //判断当前循环链表是否是最后一个自身自己
                if(temp.nextNode==temp){
                    break;
                //当前节点为第一个的时候怎么删除处理
                }else if(temp==link.headNode.nextNode){
                    //获取对应的末尾节点
                    DoubleLinkedNode lastNode=link.headNode;
                    while(lastNode.nextNode!=null){

                        lastNode=lastNode.nextNode;
                        if(lastNode.nextNode==link.headNode.nextNode){
                            break;
                        }

                    }
                    //更新末尾节点信息
                    lastNode.nextNode=temp.nextNode;

                    temp.nextNode.preNode=lastNode;

                    //更新头节点的指向
                    link.headNode.nextNode=temp.nextNode;
                //最后一个和中间怎么删除及处理
                }else
                {
                    currNode.nextNode=temp.nextNode;
                    temp.nextNode.preNode=currNode;
                }
                numberCount=0;
            }
            currNode=temp;
        }
    }
}

单向链表代码(不带头结点)
class SingleLoopLinkedDemo{
	public static void main(String[] args) {
		SingleLoopLinked singleLinekd2=new SingleLoopLinked();
        System.out.println("链表的有效个数"+singleLinekd2.getLinkedValidNumber());
        singleLinekd2.getBottomNode(0);
        int count=0;
        MyNode2 currNode=singleLinekd2.headNode;
        while(true){
            currNode=currNode.nextNode;
            count++;
            if(count%3==0){
                count=0;
                System.out.println(currNode.obj.toString());
                singleLinekd2.deleteNode(currNode.obj);
                if(singleLinekd2.headNode.nextNode==null) break;
            }
        }
    }
}
//创建一个单向循环链表
class SingleLoopLinked{
    //创建一个头节点用于牵引整个链表的第一个节点信息
    public  MyNode2 headNode=new MyNode2();
    //计算单链表的有效个数
    public Integer getLinkedValidNumber(){

        MyNode2 currNode=headNode;
        Integer coutNumber=0;
        while(currNode.nextNode!=null){
            coutNumber++;
            currNode=currNode.nextNode;
            if(currNode.nextNode==headNode.nextNode)break;
        }
        return coutNumber;
    }

    //获取倒数第几个节点
    public void getBottomNode(Integer bottomNumber){
        MyNode2 currNode=headNode;
        if(currNode.nextNode!=null){
            for(int index=0;index<=(getLinkedValidNumber()-bottomNumber);index++){
                currNode=currNode.nextNode;
            }
            System.out.println("整个链表的倒数"+bottomNumber+"个值内容为"+currNode.obj.toString());
        }
        System.out.println("没有");
    }

    //创建一个循环排序添加链表方法
    public void addNode(Object value){
        //创建一个新节点封装新信息
        MyNode2 newNode=new MyNode2(value);
        MyNode2 currNode=headNode;
        MyNode2 temp=null;

        //遍历整个链表
        while(currNode.nextNode!=null){
            temp=currNode.nextNode;
            if((Integer)temp.obj>(Integer) value){
                break;
            }
            //更新当前节点信息
            currNode=temp;

            //判断链表是否是最后一个节点
            if(currNode.nextNode==headNode.nextNode)break;
        }

        //当链表为空怎么处理新节点
        if(currNode.nextNode==null){
            newNode.nextNode=newNode;
            currNode.nextNode=newNode;
        }
        //当新节点为链表的第一个节点怎么处理
        else if(currNode==headNode){
           //获取最后一个节点
            MyNode2 lastNode=headNode;
            while(lastNode.nextNode!=null){
                lastNode=lastNode.nextNode;
                if(lastNode.nextNode==headNode.nextNode)break;
            }
            newNode.nextNode=lastNode.nextNode;
            //更新最后一个节点信息
            lastNode.nextNode=newNode;
            currNode.nextNode=newNode;
        }else{
            newNode.nextNode=currNode.nextNode;
            currNode.nextNode=newNode;
        }
    }
    public void deleteNode(Object obj){
        MyNode2 currNode=headNode;
        MyNode2 temp=null;
        while(currNode.nextNode!=null){
            temp=currNode.nextNode;
            if(temp.obj.equals(obj)){

                //判断是否是第一个
                if(temp==headNode.nextNode){

                    //判断是否是整个链表唯一一个
                    if(temp.nextNode==temp) {
                        headNode.nextNode=null;
                        break;
                    }
                    //获取最后一个节点
                    MyNode2 lastNode=headNode;
                    while(lastNode.nextNode!=null){
                        lastNode=lastNode.nextNode;
                        if(lastNode.nextNode==headNode.nextNode)break;
                    }
                    lastNode.nextNode=temp.nextNode;
                    currNode.nextNode=temp.nextNode;
                }else{
                    currNode.nextNode=temp.nextNode;
                }
                break;
            }
            currNode=temp;
            if(currNode.nextNode==headNode.nextNode)break;

        }
    }
    public void showNode(){
        MyNode2 currNode=headNode;
        while(currNode.nextNode!=null){
            System.out.println(currNode.nextNode);
            try {
                Thread.sleep(400);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            currNode=currNode.nextNode;
        }
        System.out.println("当前链表没有内容");
    }
}

//创建一个节点类
class MyNode2{
    public Object obj;
    public MyNode2 preNode;
    public MyNode2 nextNode;
    public MyNode2(){}
    public MyNode2(Object obj){
        this.obj=obj;
    }
    @Override
    public String toString() {
        return ("当前节点内容:"+obj+"下一个节点:"+(nextNode==null?"空":""+nextNode.obj)+"上一个节点"+(preNode==null?"空":""+preNode.obj));
    }
}

结果

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值