JAVA数据结构之链表【无dummyNode】形式

LinkedList

Node结点

  • data域
  • 下个结点的指向

Node结点代码

private class Node {
    public E e;
    public Node next;

    public Node(E e, Node next) {
        this.e = e;
        this.next = next;
    }

    public Node(E e) {
        this(e, null);
    }

    public Node() {
        this(null, null);
    }

    @Override
    public String toString() {
        return e.toString();
    }
}

链表结构表达

  • 链表中需要头结点
    • Node head = new Node();
  • 需要size记录拥有的元素个数
public class LinkedList<E> {
    private Node head;
    private int size;

    /***构造函数***/
    //只需要空参构造函数
    public LinkedList(){
        head = null;
        size = 0;
    }

    /*******增*******/
    // 这因为,头结点和中间结点有差异,所以需要分别讨论。此处可以优化

    public void add(int index, E e){
    //判断index是否正确
        if(index < 0 || index>size){
            throw new IllegalArgumentException("Add failed.Illegal index");
        }
        //判断当index为0的时候进行头部添加
        if(index == 0){
            addFirst(e);
        }else{
        //当不为头结点时,建立结点指针prev从头结点开始遍历到指定index位置
            Node prev = head;
            for(int i = 0;i<index-1;i++){
                prev = prev.next;
            }
            //在此处插入节点
            prev.next = new Node(e,prev.next);
            //size++
            size++;
        }
    }

    public void addFirst(E e){
//        Node node = new Node(e);
//        node.next = head;
//        head = node;
//      简化书写
        head = new Node(e,head);
        size++;
    }
    public void addLast(E e){
        add(size, e);
    }
    /*********查*******/
    //获取链表中的元素个数
    public int getSize(){
        return size;
    }
    //返回链表是否为空
    public boolean isEmpty(){
        return size==0;
    }

    /******改******/
    public void set(int index,E e){
        if(index < 0 || index>size){
            throw new IllegalArgumentException("Set failed.Illegal index");
        }
        //从头结点,开始遍历
        Node prev = head;
        for(int i = 0;i<index;i++){
            prev = prev.next;
        }
        prev.e = e;
    }
    /*****************删******************/
    public E remove(int index){
        if (index < 0 || index>=size){
            throw new IllegalArgumentException("Removed failed.Illegal index");
        }
        //建立结点引用prev,遍历到要删除节点的头一个节点
        Node prev = head;
        for(int i = 0;i<index;i++){
            prev = prev.next;
        }
        //建立删除结点引用delNode,prev.next
        Node delNode = prev.next
        //prev的下一个结点跳过删除结点,指向下下个结点
        prev.next = prev.next.next;
        //将要删除的结点指向下一个结点的引用赋值为null
        delNode.next = null;
        size -- ;
        //返回删除结点的数据域
        return delNode.e;
    }

    public E removeFirst(){
        remove(0);
    }

    public E removeLast(){
        remove(size - 1);
    }
}

注意:是结点是引用,指向同一个地址的结点,不论是哪一个结点修改,其余结点也会被动修改。

head 结点只是存储,链表的起始位置信息,不存储其他信息。

这样要分两次考虑,
- 第一个结点【区分head】
- 中间结点

为了简化思考方式,可以优化,在第一个结点(不是head)之前加一个不存任何数据的结点dummyNode,这样所有要操作的结点都是中间结点。不用思考第一个结点

猜你喜欢

转载自blog.csdn.net/weixin_41263632/article/details/81780187