链表

链表

链表是一种线性结构

上述分别为链表的逻辑结构和内存结构(实际在内存中存储顺序是不连续的)

链表的的每一个节点有两部分组成,第一部分存储相应的数据,另一部分存储下一个节点的地址,最后一个节点的next指向null

链表的特点是增删快,查找慢

双向链表

public class SingleNode {
//双向链表
    //相对于单向链表来讲有两个方向可以操作链表
    //两个方向定义头结点和尾节点
    class DoubkeLikendList{
        Node head = new Node(0,null);
        Node tail = new Node(0,null);
        public void add(Node node){
            Node temp = head;
            while(true){
                if(temp.next==null){
                    temp.next=node;
         //与单向链表相同,将最后一个节点的next指向新加入的节点
                    node.pre=temp
                //将新加入的节点的上一个指向此时的temp(新加入的上一个)
                    tail=node;
                    break;
                }
                temp=temp.next;
            }
        }
        public void change(int no){
            //按照编号修改姓名
            //与单向链表类似
            Node temp = head;
            while(true){
                if(temp.no==no){
                    temp.name="新名字";
                    break;
                }
                if(temp.next==null){
                    System.out.println("没有要找到删除的节点");
                    break;
                }
                temp=temp.next;
            }
        }
        //按照指定编号删除节点
        //相对于单向链表来讲,可以实现自我删除,而单向链表需要一个辅助节点
        public void delete(int no){
            Node temp = head;
            while(true){
                if(temp.no==no){
                    if(temp.pre==null){
                        temp.next.pre=temp.pre;
                        //防止空指针异常
                    }else if(temp.next==null){
                        temp.pre.next=temp.next;
                        //防止空指针异常
                    }else{
                        temp.next.pre=temp.pre;
                        //将该节点的下一个的前一个指向给节点的前一个
                        temp.pre.next=temp.next;
                        //将该节点的前一个的下一个指向给节点的下一个
                 //经过上面两步以后该节点就成为一个“垃圾”,有JVM自动回收
                    }
                    break;
                }
                if(temp.next==null){
                    System.out.println("没有要找到删除的节点");
                    break;
                }
                temp=temp.next;
            }
        }
        public  void allNode(){
            //利用尾节点遍历
            Node temp = tail;
            while(true){
                if(temp.next==null){
                    System.out.println(temp);
                    break;
                }
                System.out.println(temp);
                temp=temp.next;
            }
        }

    }

    class Node{
        public  int no;
        public  String name;
         public Node next;//指向该节点的下一个节点
        public  Node pre;//指向该节点的前一个节点
        
        public Node(int no , String name) {
            this.no = no;
            this.name=name;
        }
        @Override
        public String toString() {
            return "Node{" +
                    "no=" + no +
                    ", name='" + name ;
        }
    }
}

循环链表

、、最后一个节点指向第一个节点构成一个环形

一约瑟夫问题为例

public class CircleNode {
    //最后一个节点的next指向第一个节点
    /*
    约瑟夫问题:
    约瑟夫问题是个有名的问题:N个人围成一圈,从第一个开始报数,第M个将出队,最后剩下一个。
     */
    class MethodYuesefu{
        Node2 first;
        public void addN(int N){
            //按输入的N,创建指定大小的初始链表
            if(N<1){
                System.out.println("输入的数据不合法");
                return;
            }
            Node2 assman  = null;//辅助节点
            for (int i = 1; i < N+1; i++) {
                Node2 man = new Node2(i);
                if(i==1){
                    first=man;
                    first.setNext(first);
                    assman = first;
                    //只有一个数据的链表,自我构成循环
                }else{
                    assman.setNext(man);
                    man.setNext(first);
                    //将新加入的节点的next指向第一个构成循环(新加入的一定是最后一个)
                    assman=man;
                }
            }
        }
        public void allMan(){
            Node2 temp = first;
            if(first==null){
                System.out.println("链表为空~~");
                return;
            }
            while(true){
            System.out.println(temp);
            if(temp.getNext()==first){
                //遍历结束条件是重新找到了第一个节点
                break;
            }
            temp=temp.getNext();
            }
        }

        /**
         * 
         * @param startNo 从第几个编号开始数
         * @param num  每一次数几个数
         * @param N  总人数
         */
        public void countMan(int startNo,int num,int N){
            if(first==null|| startNo<1||startNo>N){
                System.out.println("输入的数据不符合要求");
                return;
            }
            Node2 helper = first;//用来指向first的前一个节点
            while(true){
                //找到first的前一个元素,并将其赋值给helper 
                if (helper.getNext()==first){
                    break;
                }
                helper=helper.getNext();
            }
            for (int i = 0; i < startNo-1; i++) {
                //将first移到开始的位置
                first=first.getNext();
                helper = helper.getNext();
            }
            while(true){
                if(helper==first){
                    //只剩下一个数据
                    System.out.println("剩下的编号");
                    break;
                }
                for (int i = 0; i <num-1; i++) {
                    //数数
                    first=first.getNext();
                    helper = helper.getNext();
                }
                System.out.println("出圈:"+first.getNo());
                first=first.getNext();
                helper.setNext(first);
                //将数到的节点删除,直接将helpter指向新first,那么原新的first就访问不到了成为了垃圾
            }
        }
    }
    class Node2{
        private int no;
        private Node2  next;

        public Node2(int no) {
            this.no = no;
        }

        @Override
        public String toString() {
            return "Node2{" +
                    "no=" + no +
                    '}';
        }

        public int getNo() {

            return no;
        }

        public void setNo(int no) {
            this.no = no;
        }

        public Node2 getNext() {
            return next;
        }

        public void setNext(Node2 next) {
            this.next = next;
        }
    }
}
原文地址:https://www.cnblogs.com/susexuexi011/p/14078350.html