LinkedList底层源码的简单实现(常用方法)

import java.util.NoSuchElementException;

public class LinkedListTest<E> {
    int size=0;
    //指向第一个结点的指针
    Node<E> first;
    //指向最后一个结点的指针
    Node<E> last;


    public LinkedListTest() {

    }

    //往首结点前面添加元素,先让first指针指向当前结点,如果首结点为null,说明这个链表是空的,当前这个结点就是首结点,也是尾结点,让last指针也指向它,否则,旧的首结点的prev他应该只想当前节点
    public void linkFirst(E e) {
        Node<E> f=first;//先定义一个指针指向首结点
        //这个是新的首结点,将它的next指向旧首结点的指针
        Node<E> newNode=new Node<>(null,e,f);
        first=newNode;//指针指向当前的新结点
        if(f==null)//说明链表还是空的,那首尾指针都应该是当前的结点
            last=newNode;
        else //将旧的头结点和新的头结点联系起来
            f.prev=newNode;
        size++;
    }

    //添加新的尾结点,先让last指针指向当前结点,如果尾结点为null,则说明当前链表为空,那么让first指针指向当前结点,否则,原来的尾结点的next应该指向当前结点
    public void linkLast(E e) {
        Node<E> l=last;

        //将这个新结点的prev指向旧尾结点的指针
        Node<E> newNode=new Node<>(l,e,null);
        last=newNode;

        //如果尾结点是null,说明连表示空的,就把首结点的指针也指向当前元素
        if(l==null)
            first=newNode;
        //否则旧尾指针的next指向新尾指针
        else l.next=newNode;
        size++;
    }

    //向succ结点前面添加一个结点,先得到succ的前驱结点,如果前驱结点为null,相当于是往头结点前添加元素,就让first指针指向当前节点,否则,secc前驱结点的next指针应该指向当前节点
    public void linkBefore(E e,Node<E> succ) {
        Node<E> pred=succ.prev;
        //当前结点的prev指针指向pred,next指针指向succ
        Node<E> newNode=new Node<>(pred,e,succ);
        succ.prev=newNode;

        //如果succ就是首结点,那newNode就会变成新的首结点,就需要将first指针指向newNode
        if (pred==null)
            first=newNode;
        //如果pred存在,则将他的next指向newNode
        else pred.next=newNode;
        size++;

    }


    //获取链表首结点的内容
    public E getFirst() {
        Node<E> f=first;
        if(f==null)
            throw new NoSuchElementException();
        return f.item;
    }


    //获取链表尾结点的内容
    public E getLast() {
        Node<E> l=last;
        if(l==null)
            throw new  NoSuchElementException();
        return l.item;
    }

    public E removeFirst() {
        Node<E> f=first;
        if(f==null)
            throw new NoSuchElementException();
        return unlinkFirst(f);
    }

    public E removeLast() {
        Node<E> l=last;
        if(l==null)
            throw new NoSuchElementException();
        return unlinkLast(l);
    }

    //删除首结点,如果正常情况下,删除首结点以后由首结点的下一个来当首结点,需要将下一个首结点的prev置为null,如果首结点没有下一个元素,则说明这个链表空了,last置为null
    private E unlinkFirst(Node<E> f) {
        //先拿到首结点的元素值
        E element=f.item;
        Node<E> next=f.next;
        f.item=null;
        f.next=null;

        //新的首结点就是f的next
        first=next;
        //如果整个链表中只有一个f结点,那么现在last指针也应该是空的
        if(next==null)
            last=null;
        //next结点就是首结点,next的prev就是空
        else next.prev=null;
        size--;
        return element;
    }

//删除尾结点,正常情况下来说,删除尾结点就需要尾结点的前一个结点作为新的尾结点,如果尾结点不存在前驱,即链表中只有要删除的这个结点的话,那么就可以直接将fist指针置空,表示整个链表中没有元素了,
    public E unlinkLast(Node<E> l) {
        E element=l.item;
        //新的尾结点
        Node<E> prev=l.prev;

        l.item=null;
        l.prev=null;

        last=l;
        //如果l本来就是链表中的唯一一个结点,l删除后,first也应该置为空
        if(prev==null)
            first=null;
        //否则,尾结点的next应该是空
        else prev.next=null;
        size--;
        return element;
    }

    //删除x结点,如果x是首结点,就需要让首结点的下一个来作为新的首结点,所以first指针应该只想x的下一个结点,如果x是尾结点,就需要让尾结点的前一个来作为新的尾结点,所以last指针应该指向的是x的前驱
    public E unlink(Node<E> x) {
        E element=x.item;
        Node<E> next=x.next;
        Node<E> prev=x.prev;

        //如果X是首结点,那么first指针应该指向x的next
        if(prev==null)
            first=next;
        //否则,x.prev.next与x.next相连,
        else  {
            prev.next=next;
            x.prev=null;
        }

        //如果x是尾结点
        if(next==null)
            last=prev;
        else {
            next.prev=prev;
            x.next=null;
        }
        x.item=null;
        size--;
        return element;
    }


    public void addFirst( E e) {
        linkFirst(e);
    }

    public void addLast(E e) {
        linkLast(e);
    }

    public boolean contains(Object o) {
        return indexOf(o)!=-1;
    }

    public int indexOf(Object o) {
        int index=0;
        if(o==null) {
            for(Node<E> x=first;x!=null;x=x.next) {
                if(x.item==null)
                    return index;
                index++;
            }
        }
        else {
            for(Node<E> x=first;x!=null;x=x.next) {
                if(o.equals(x.item))
                    return index;
                index++;
            }
        }
        return -1;
    }

    public int size() {
        return size;
    }

    public boolean add(E e) {
        linkLast(e);
        return true;
    }


    //根据元素值删除结点
    public boolean remove(Object o) {
        if(o==null) {
            for(Node<E> x=first;x!=null;x=x.next) {
                if(x.item==null) {
                    unlink(x);
                    return true;
                }
            }
        }
        else {
            for(Node<E> x=first;x!=null;x=x.next) {
                if(o.equals(x.item)) {
                    unlink(x);
                    return true;
                }
            }
        }
        return false;
    }

    public E get(int index) {
        checkElementIndex(index);
        return node(index).item;
    }


    //将index对应的元素值改成element
    public E set(int index ,E element) {
        checkElementIndex(index);
        Node<E> x=node(index);
        E oldVal=x.item;
        x.item=element;

        return oldVal;
    }

    //往对应下标中添加元素
    public void add(int index,E element) {
        checkElementIndex(index);
        //直接往尾结点添加元素
        if(index==size)
            linkLast(element);
        else {
            //向index的结点前添加一个element结点
            linkBefore(element,node(index));
        }
    }


    //根据元素下标删除结点
    public E remove(int index) {
        checkElementIndex(index);
        return unlink(node(index));
    }

    //返回尾结点的元素值
    public E peek() {
        Node<E> f=last;
        return (f==null)?null:f.item;
    }

    //删除链表头结点
    public E poll() {
        Node<E> f=first;
        return (f==null)?null:unlinkFirst(f);
    }

    public boolean offer(E e) {
        return add((e));
    }

    public boolean offerFirst(E e) {
        addFirst(e);
        return true;
    }

    public boolean offerLast(E e) {
        addLast(e);
        return true;
    }

    public E peekFirst() {
        Node<E> f=first;
        return (f==null)?null:f.item;
    }

    public E peekLast() {
        Node<E> l=last;
        return (l==null)?null:l.item;
    }

    public E pollFirst() {
        Node<E> f=first;
        return (f==null)?null:unlinkFirst(f);
    }

    public E pollLast() {
        Node<E> l=last;
        return (l==null)?null:unlinkLast(l);
    }

    //添加新的头结点
    public void push(E e) {
        addFirst(e);
    }


    //得到链表的首结点
    public E pop() {
        return removeFirst();
    }

    //根据下标获取到链表元素
    Node<E> node(int index) {
        //判断index的大小然后决定是从前往后找还是从后往前找
        if(index<(size>>1)) {
            Node<E> x=first;
            for(int i=0;i<index;i++)
                x=x.next;
            return x;
        }
        else {
            Node<E> x=last;
            for(int i=size-1;i>index;i--)
                x=x.prev;
            return x;
        }
    }

    public void checkElementIndex(int index) {
        if(!isElementIndex(index))
            throw new IndexOutOfBoundsException();
    }

    private boolean isElementIndex(int index) {
        return index>=0&&index<size;
    }
    private static class Node<E> {
        E item;
        Node<E> next;
        Node<E> prev;

        Node(Node<E> prev,E element,Node<E> next) {
            this.item=element;
            this.prev=prev;
            this.next=next;
        }
    }

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值