2019/9/16 (双链表+循环链表 + 单链表解决Joseph问题)

2019/9/16 (双链表+循环链表 + 单链表解决Joseph问题)

学习视频来源:https://www.bilibili.com/video/BV1B4411H76f?p=29

双链表

package LinkedList.doubleLinkedList;

import LinkedList.MyLinkedList;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class DoubleLinkedList {
    private HeroNode head;
    private HeroNode tail;
    private int size;
    @Data
    static
    class HeroNode{
        private int no;
        private String name;
        private HeroNode pre;
        private HeroNode next;
        public HeroNode() {
            pre = null;
            next = null;
        }
        public HeroNode(int no, String name) {
            this.no = no;
            this.name = name;
            pre = null;
            next = null;
        }
        @Override
        public String toString() {
            return "HeroNode{" +
                    "no=" + no +
                    ", name='" + name + '\'' +
                    '}';
        }
    }
    public HeroNode getFirst(){
        return this.head;
    }
    public HeroNode getLast(){
        return this.tail;
    }
    public void display(){
        System.out.println("========================");
        HeroNode tmp = this.head;
        while(tmp!=null){
            System.out.println(tmp);
            tmp = tmp.next;
        }
        System.out.println("over=================");
    }
    public void addLast(HeroNode node) {
        if (isEmpty()){
            head = node;
        }
        if (isNotEmpty()){
            tail.next = node;
            node.pre = tail;
        }
        tail = node;
        size++;
    }
    public void addByOrder(HeroNode node){
        HeroNode preHead = new HeroNode();
        preHead.next = this.head;
        HeroNode tmp = preHead;
        while(true){
            if (tmp.next==null){
                addLast(node);
                break;
            }
            if (tmp.next.getNo()> node.getNo()){
                if(tmp.next==head){
                    preHead.next=node;
                    node.next=head;
                    head.pre=node;
                    head = node;
                    size++;
                }else {
                    node.next=tmp.next;
                    tmp.next.pre=node;
                    tmp.next=node;
                    node.pre=tmp;
                    size++;
                }
                break;
            }
            tmp = tmp.next;
        }
    }
    public boolean isEmpty(){
        return size==0;
    }
    public boolean isNotEmpty(){
        return !isEmpty();
    }
    public void remove(int index){
        HeroNode rmvNode = getAt(index);
        if (rmvNode.pre == null){
            this.head = rmvNode.next;

            rmvNode.next.pre = null;
            rmvNode.next = null;
            return ;
        }
        if (rmvNode.next == null){
            this.tail=rmvNode.pre;
            rmvNode.pre.next = null;
            rmvNode.pre = null;
            return ;
        }
        rmvNode.pre.next = rmvNode.next;
        rmvNode.next.pre = rmvNode.pre;
        rmvNode = null;
    }

    /**
     * 很骚的方法是把size右移2位,相当于处以2 在与index比较看是从前遍历还是后面
     * @param index
     */
    public HeroNode getAt(int index){
        HeroNode tmp = this.head;
        for (int i = 1; i <=index-1; i++) {
            tmp = tmp.next;
        }
        return tmp;
    }

}

双链表测试

package LinkedList.doubleLinkedList;

public class DoubleLinkedListTest {
    public static void main(String[] args) {
        DoubleLinkedList.HeroNode a1 = new DoubleLinkedList.HeroNode(1,"2");
        DoubleLinkedList.HeroNode a2 = new DoubleLinkedList.HeroNode(2,"2");
        DoubleLinkedList.HeroNode a3 = new DoubleLinkedList.HeroNode(3,"2");
        DoubleLinkedList list = new DoubleLinkedList();
        list.addByOrder(a1);
        list.addByOrder(a3);
        list.addByOrder(a2);
        list.display();
        System.out.println(list.getSize());
        System.out.println(list.getHead());
        System.out.println(list.getTail());
        System.out.println(list.getAt(3));
        list.remove(1);
        list.display();
        System.out.println(list.getHead());
        System.out.println(list.getTail());
    }
}

单循环链表

package LinkedList.单循环链表;


public class SingleCircleLinkedList {
    private Node rear;
    private int size;
    static class Node{
        private int num;
        private Node next;
        public int getNum() {
            return num;
        }
        public void setNum(int num) {
            this.num = num;
        }
        public Node(int num) {
            this.num = num;
        }
    }
    public Node getHead(){
        return this.rear.next;
    }

    public Node getRear() {
        return rear;
    }

    public void setRear(Node rear) {
        this.rear = rear;
    }

    public SingleCircleLinkedList() {
        rear = null;
        size = 0;
    }

    public int getSize() {
        return size;
    }

    public void display(){
        System.out.println("========================");
        if (this.size==0){
            return;
        }
        Node tmp = rear.next;
        int counts = getSize();
        while((counts--)>0){
            System.out.println(tmp.getNum());
            tmp = tmp.next;
        }
        System.out.println("============OVER============");
    }
    public void addLast(int data){
        Node node = new Node(data);
        if (size==0){
            rear = node;
            rear.next = rear;
            size++;
            return;
        }
        node.next = rear.next;
        rear.next = node;
        rear = node;
        size++;
    }
    public void addNum(int num){
        if (num<1){
            System.out.println("num must >1");
            return;
        }
        for (int i = 1; i <=num; i++) {
            addLast(i);
        }
    }
    public Node getAt(int index){
        if (this.size==0){
            return null;
        }
        Node tmp = rear;
        for (int i = 1; i <=index; i++) {
            tmp = tmp.next;
        }
        return tmp;
    }
    public void removeNode(int index){
        if (size==0){
            return ;
        }
        if (index>size || index<1){
            return;
        }
        Node pre ;
        if (index==1){
            pre = rear;
        }else {
            pre = getAt(index-1);
        }
        Node rmvNode = pre.next;
        System.out.println("getOurNum:          "+rmvNode.getNum());
        pre.next = rmvNode.next;
        if (index==size){
            rear = pre;
        }
        size--;
    }

单链表解决Joseph问题:

解决步骤

  1. 需求创建一个辅助指针helper,事先指向链表尾部
  2. 小孩报数前,找到k的位置,先让first和helper移动(k-1)次
  3. 当小孩报数时,helper 和first 移动 (m-1)%size次
  4. 这时候,first就是要删除的节点,出圈
  5. 最后一个节点条件为 first = helper.
    /**
     * Joseph 问题为:设编号为1,2,···n的人围坐一圈,约定编号为k(1<=k<=n)的人开始报数,
     * 数到m的人出列,它的下一位又从1开始报数,数到m的人又开始出列,以此类推,求出圈顺序。
     */
    public void joseph(int k,int m){
        if (rear ==null || k<1 || k>size){
            System.out.println("输入有误");
            return;
        }
        Node helper = rear;
        Node first = rear.next;
        for (int i = 1; i <k; i++) {
            helper = helper.next;
            first = first.next;
        }
        while(true){
            if (helper == first){ // 最后一个节点了
                break;
            }
            for (int i = 0; i < (m-1)%size; i++) {
                helper = helper.next; // first 为删除的节点
                first = first.next;
            }
            System.out.println("小孩出圈的位置   +   "+first.getNum());
            helper.next = first.next;
            first = first.next;
            size--;
        }
        System.out.println("最后留在圈中为:"+first.getNum());

    }
}

posted @ 2021-09-16 18:34  能借我十块钱吗  阅读(24)  评论(0编辑  收藏  举报