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();
    }
}
原文地址:https://www.cnblogs.com/HigginCui/p/6093450.html