数据结构-双向链表&&约瑟夫环

为什么要用双向链表?单向链表的劣势

管理单向链表的缺点分析:
1)单向链表,查找的方向只能是一个方向,而双向链表可以向前或者向后查找。
2)单向链表不能自我删除,需要靠辅助节点﹐而双向链表,则可以自我删除,所以前面我们单链表删除时节点,总是找到temp,temp是待删除节点的前一个节点(认真体会).
3)分析了双向链表如何完成遍历,添加,修改和删除的思路

双向链表代码实现


class HeroNode{
    public  int no;          //data
    public  String name;       //data
    public  String nickname;   //data
    public  HeroNode next;     //用对象模拟指针,来指向下一个节点 next
    public  HerNode pre;       //指向上一个节点

    public HeroNode(int no, String name, String nickname) {
        this.no = no;
        this.name = name;
        this.nickname = nickname;
        this.next = next;
    }

    @Override
    public String toString() {
        return "HeroNode{" +
                "no=" + no +
                ", name='" + name + '\'' +
                ", nickname='" + nickname + '\'' +
                '}';
    }
}

双向链表可以实现自我删除
数据结构-双向链表&&约瑟夫环_第1张图片

temp.pre.next=temp.next;
temp.next.pre=temp.pre;

双向链表新增节点

    public void add(HeroNode heroNode) {

        //定义一个辅助指针找到末节点
        HeroNode temp = head;      //从头开始找
        while (temp.next != null) {
            temp = temp.next;       //注意next是节点对象
        }
        temp.next = heroNode;//将新增的节点添加到最后一个节点的next
        heroNode.pre=temp;   //区别之处,将新增的前指针指向原来的最后一个节点
    }

约瑟夫环

约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知 n 个人(以编号1,2,3…n分别表示)围坐在一张圆桌周围。从编号为 k 的人开始报数,数到 m 的那个人出圈;他的下一个人又从 1 开始报数,数到 m 的那个人又出圈;依此规律重复下去,直到剩余最后一个胜利者。

约瑟夫问题有很多解法,除了数组,迭代,递归,其中有个解法就是单向环形链表。

单向环形列表即首位节点相连。

数据结构-双向链表&&约瑟夫环_第2张图片
解决问题思路:
数据结构-双向链表&&约瑟夫环_第3张图片
数据结构-双向链表&&约瑟夫环_第4张图片

创建单向循环链表

思路:用两个指针,一个指针始终指向首节点,首节点先自循环,然后定义一个辅助指针来辅助新增。

//创建一个环形单向链表
class  CircleLinkedList{
    //创建一个first节点,当然没有编号
    private  Boy first=null;

    public  void add(int nums){
        if(nums<1){
            System.out.println("nums错误");
            return;
        }
        Boy current = null;   //辅助指针
        //第一个节点先形成环
        for (int i = 1; i <=nums ; i++) {
            Boy boy=new Boy(i);
            if(i==1){
                first=boy;
                first.setNext(first);  //自环
                current=first;
            }else{
                current.setNext(boy);  //当前节点的next指向新增节点
                boy.setNext(first);   //新增节点的next指向头节点
                current=boy;       //将current指向新增的节点
            }
        }

    }

    public  void show() {
        if (first == null) {
            System.out.println("不存在");
            return;
        }
        Boy current = first;   //辅助指针
        while (true) {
            System.out.println(current.getNo());
            if (current.getNext() == first) {
                System.out.println("遍历结束");
                break;
            }
            current = current.getNext();
        }
    }
    }

解决约瑟夫问题,节点出圈

思路分析
数据结构-双向链表&&约瑟夫环_第5张图片

  /**
     *
     * @param startNo   从第几个开始数数
     * @param countNo   数几下
     * @param nums   总共多少个
     */
    public  void countGo(int startNo,int countNo,int nums) {
    //数据校验
        if(first==null||startNo<1||startNo>nums){
            System.out.println("数据错误");
            return;
        }
        Boy helper=first;
        //让helper指向最后一个节点
        while (true){
            if(helper.getNext()==first)  //说明helper指向了最后一个节点
            {
                break;
            }
            helper=helper.getNext();  //关于这里为什么不用.next,是因为我的参数是private的呀=-=
        }
        //first和helper指针移动k-1次,移动到开始的人那里
        for(int j=0;j<startNo-1;j++){
            first=first.getNext();
            helper=helper.getNext();

        }
        //执行出圈操作,当圈内只有一个节点时,游戏结束
        //即当helper指针追上了first指针,说明只有一个节点了
         while (true){
             if(helper==first){
                 System.out.println("只有一个节点le");
                 break;
             }
             //出圈操作,要叫几下,移动n-1次
             for(int j=0;j<countNo-1;j++){
                 first=first.getNext();  //此时first是要出圈的节点
                 helper=helper.getNext();   //helper是出圈节点的前一个节点
             }
             System.out.println("出圈节点"+first.getNo());
             //出圈
             first=first.getNext();
             helper.setNext(first);
         }
    }

测试

    public static void main(String[] args) {
        CircleLinkedList circleLinkedList=new CircleLinkedList();

       circleLinkedList.add(5);
       circleLinkedList.countGo(1,2,5);
       circleLinkedList.show();

    }

你可能感兴趣的:(数据结构,链表,数据结构)