• 2.4_线性表的链式存储结构_单链表具体实现


    【思路简述】

      看了很多网上的相关java实现单链表的思路,发现很多都没有设置一个头指针,因此,在我的自定义链表类MySingleLinkedList类中的head成员变量即为头指针,head结点其数据域默认为空,其指针域即为头指针,所以判断MySingleLinkedList对象是否为空,要判断其head.next()是否为空才可以。并在MySingleLinkedList的构造方法中同时初始化head,即 this.head=new Node();

    【MySingleLinkedList.java实现类】

    package com.Higgin.LinkList;
    
    /**
     * 单链表
     * @author Higgin
     */
    public class MySingleLinkedList {
        /**
         * 结点内部类
         */
        class Node{
            private Object obj;  //数据域
            private Node next;     //指针域
            public Node(Object obj, Node next) {
                this.obj = obj;
                this.next = next;
            }
            public Node(Object obj){
                this(obj,null);
            }
            public Node(){
                this(null,null);
            }
        }
        /**
         * 头指针结点,其指针域为头指针(并不是头结点)
         */
        private Node head;   
        
        /**
         * 构造方法,其中实例化head头指针
         */
        public MySingleLinkedList(){
            this.head=new Node();  //初始化head对象
        }
        
        /**
         * 判断链表是否为空
         */
        public boolean isEmpty(){   //head结点(包含头指针),其数据域一直为null,利用其指针域来判断链表是否为空
            return head.next==null;  //只判断该指针域是否为空
        }
        
        /**
         * 在链表最后添加元素 
         */
        public void addLast(Object obj){
            Node newNode=new Node(obj);
            Node curNode=head;     //无需单独判断链表为空的情况
            while(curNode.next!=null){  
                curNode=curNode.next;
            }
            curNode.next=newNode;
        }
        
        /**
         *  在第index位置之前插入对象obj
         */
        public void add(int index,Object obj){
            Node newNode=new Node(obj); //初始化被插入的结点
            if(index==0){
                newNode.next=head.next;  //要插入的结点newNode的指针域指向head的指针域,可防止断链
                head.next=newNode;       //再将head的指针域指向新插入的结点
                return;
            }
            //保证了 当前的index>0
            Node curNode=this.getNode(index-1);  //获取要插入位置(如2)的前一个结点(如1)
            newNode.next=curNode.next;
            curNode.next=newNode;
        }
        
        /**
         * 获取第index个结点(从头指针指向的那个结点开始算为第0个)
         */
        public Node getNode(int index){
            Node curNode=head;
            if(index<0||index>this.size()-1){  //要和数组的思维一样!注意head后面那个结点称为第0个,所以要size()-1
                throw new IndexOutOfBoundsException("Index: "+index+" Size: "+this.size()); 
            }
            int i=0;
            for(i=0;i<index && curNode!=null;i++){
                curNode=curNode.next;  //curNode不断向后走
            }
            if(i!=index){
                throw new IndexOutOfBoundsException("Index: "+index+" Size: "+this.size()); 
            }
            return curNode.next;
        }
        
        /**
         * 获取第index个结点的数据域对象
         */
        public Object getObject(int index){
            return getNode(index).obj;
        }
        
        /**
         * 获取链表的长度(不包含头指针)
         */
        public int size(){
            if(this.head.next==null){
                return 0;
            }else{
                Node curNode=head;
                int i=0;
                while(curNode.next!=null){
                    curNode=curNode.next;
                    i++;
                }
                return i;
            }
        }
        
        /**
         * 删除第index个结点
         */
        public void deleteNode(int index){
            if(index<0||index>size()-1){  //这里就排除了链表长度小于index的问题
                throw new IndexOutOfBoundsException("Index: "+index+" Size: "+this.size()); 
            }
            //删除链表的第一个元素
            if(index==0){
                Node curNode=head.next;
                head.next=curNode.next;  //本质即 head.next=head.next.next.next;
                curNode.next=null; 
                curNode.obj=null;
            }
            Node preNode=this.getNode(index-1);  //获取要删除的那个结点的前一个结点
            Node curNode=preNode.next;           //要删除的那个结点
            preNode.next=curNode.next;
            curNode.next=null;
            curNode.obj=null;
        }
        
        /**
         * 打印所有的结点
         */
        public void printAll(){
            int i=0;
            while(i<this.size()){  //这里保证了 size()>0,至少有一个结点
                System.out.println("第[ "+i +" ]个结点的数据域为: "+getObject(i).toString());
                i++;
            }
        }
        
    }

     【测试,与LinkedList进行对比】

    public class TestMySingLinkedList {
        
        //测试addLast()和size()方法
        @Test 
        public void test1(){
            MySingleLinkedList link=new MySingleLinkedList();
            System.out.println(link.size());
            link.addLast(1);
            link.addLast(1);
            link.addLast(1);
            link.addLast(1);
            System.out.println(link.size());
            
            LinkedList l =new LinkedList();
            System.out.println(l.size());
            l.add(1);
            l.add(1);
            l.add(1);
            l.add(1);
            System.out.println(l.size());
        }
        
        //测试获取链表第index个元素的对象的方法getObject(index)
        @Test
        public void test2(){
            MySingleLinkedList link=new MySingleLinkedList();
    //        System.out.println(link.getObject(0));  //此时空链表,这里应该会报错
            link.addLast(1);
            link.addLast(2);
            link.addLast(3);
            link.addLast(4);
            System.out.println(link.getObject(0)+"----"+link.getObject(1)+"----"+link.getObject(2)+"----"+link.getObject(3));
    //        System.out.println(link.getObject(5)); //超出范围,也会报错
            
            LinkedList l =new LinkedList();
    //        System.out.println(l.get(0));  //此时空链表,这里应该会报错
            l.add(1);
            l.add(2);
            l.add(3);
            l.add(4);
            System.out.println(l.get(0)+"----"+l.get(1)+"----"+l.get(2)+"----"+l.get(3));
        }
        
        //测试在第index个结点之前插入结点
        @Test
        public void test3(){
            MySingleLinkedList link=new MySingleLinkedList();
    //        link.add(1,1);
            link.add(0,0); //0
            link.add(1,1); //0,1
            link.add(2,2); //0,1,2
    //        System.out.println(link.getObject(0)+"---"+link.getObject(1)+"---"+link.getObject(2));
    //        link.add(0,8); //8,0,1,2
    //        System.out.println(link.getObject(0)+"---"+link.getObject(1)+"---"+link.getObject(2)+"---"+link.getObject(3));
    //        link.add(1,6); //8,1,0,1,2
    //        System.out.println(link.getObject(0)+"---"+link.getObject(1)+"---"+link.getObject(2)+"---"+link.getObject(3)+"---"+link.getObject(4));
            
    //        
            LinkedList l =new LinkedList();
    //        l.add(1,2);
            l.add(0,0); //0
            l.add(1,1); //0,1
            l.add(2,2); //0,1,2
            l.add(4,88);
    //        System.out.println(l.get(0)+"---"+l.get(1)+"---"+l.get(2));
    //        l.add(0,8); //8,0,1,2
    //        System.out.println(l.get(0)+"---"+l.get(1)+"---"+l.get(2)+"---"+l.get(3));
    //        l.add(1,6); //8,1,0,1,2
    //        System.out.println(l.get(0)+"---"+l.get(1)+"---"+l.get(2)+"---"+l.get(3)+"---"+l.get(4));
            
        }
        
        //测试删除第index个结点
        @Test
        public void test4(){
            MySingleLinkedList link=new MySingleLinkedList();
            link.addLast(0);
            link.add(0, 1);
            link.addLast(9);
            link.printAll();
            link.deleteNode(1);
            link.printAll();
        }
    }
  • 相关阅读:
    性能测试策略和关注指标
    ES7.17.1安装
    java 复制对象
    Java 实现树结构计算各个节点数的和
    自定义初始化ES实体类
    .net core datatable 导出 pdf 支持中文
    VSCode 快捷键(整理)
    国标平台LiveGBS GB28181接入录像机NVR、摄像头时没有通道 通道数位0的检查办法
    基于docker搭建Android cordova开发环境
    SpringBoot整合邮箱发送邮件
  • 原文地址:https://www.cnblogs.com/HigginCui/p/6093450.html
Copyright © 2020-2023  润新知