• 链表


    链表

    链表是一种线性结构

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

    链表的的每一个节点有两部分组成,第一部分存储相应的数据,另一部分存储下一个节点的地址,最后一个节点的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;
            }
        }
    }
  • 相关阅读:
    DataTable 中各种计算(笔记)
    超级强悍开源图表控件ZedGraph,请高手指教数据绑定问题!!!
    ArcGIS Engine 9.3项目迁移到ArcGIS Engine 10 报错的解决方案
    c# ,vb.net代码相互转换
    ArcGIS扩展开发(一)为 ArcGIS Desktop建立Addin插件
    设计
    正则表达式
    JSON入门
    关于Unity中资源导入
    关于Unity中的ShaderLab
  • 原文地址:https://www.cnblogs.com/susexuexi011/p/14078350.html
Copyright © 2020-2023  润新知