链式存储方式线性表之LinkedList源码解析

线性表:顺序存储结构和链式存储结构
链式存储结构的优缺点:
- 优点:删除插入效率高
- 缺点:查询效率高
image.png
image.png
循环列表:将单链表中终端结点的指针端由空指针改为指向头结点,就使整个单链表形成一个环,这种头尾相连的单链表称为单循环链表,简称循环链表
image.png
双向循环列表:双向循环链表是单向循环链表的每个结点中,再设置一个指向其前驱结点的指针域
image.png
对于空的双向循环列表
image.png
双向循环列表插入
image.png
双向列表的删除
image.png

LinkedList源码解析:双向循环列表

参数和构造函数源码解析
transient Link<E> voidLink;//这个参数代表头指针

  private static final class Link<ET> {
        ET data;//每个的数据

        Link<ET> previous, next;//前一个指针和下一个指针

        Link(ET o, Link<ET> p, Link<ET> n) {
            data = o;
            previous = p;
            next = n;
        }
    }
迭代器源码解析

参数和构造函数源码解析

  private static final class LinkIterator<ET> implements ListIterator<ET> {
       final LinkedList<ET> list;
        Link<ET> link, lastLink;//当前节点和最后一个节点
 //双向列表
  LinkIterator(LinkedList<ET> object, int location) {
            list = object;
            expectedModCount = list.modCount;//修改次数赋值
            if (location >= 0 && location <= list.size) {
               //设置当前节点为头指针
                link = list.voidLink;
               //二分查找
                if (location < list.size / 2) {
                    for (pos = -1; pos + 1 < location; pos++) {
                        //当前节点为下一个节点
                       //循序查找
                        link = link.next;
                    }
                } else {
                    for (pos = list.size; pos >= location; pos--) {
                          //倒序查找
                        link = link.previous;
                    }
                }
            } else {
                throw new IndexOutOfBoundsException();
            }
        }
}

add添加源码解析,所以add并不是添加到尾部

 public void add(ET object) {
            if (expectedModCount == list.modCount) {
                 //指向下一个节点
                 //link代表01   link.next代表原来指向的02,现在插入03
                 Link<ET> next = link.next;//原本指向的下一个节点
               //添加对象新建一个节点     link为前一个节点,next为下一个节点
                Link<ET> newLink = new Link<ET>(object, link, next);
                link.next = newLink;//当前01的指向为03
                next.previous = newLink;//02的前一个指向03
                link = newLink;//下一个节点则为03
                lastLink = null;//最后一个为空
                pos++;
                expectedModCount++;
                list.size++;
                list.modCount++;
            } else {
                throw new ConcurrentModificationException();
            }
        }

添加头部源码解析

    public void addFirst(E object) {
        addFirstImpl(object);
    }
    private boolean addFirstImpl(E object) {
        Link<E> oldFirst = voidLink.next;//原本指向01
        Link<E> newLink = new Link<E>(object, voidLink, oldFirst);//object新建一个指针对象
        voidLink.next = newLink;
        oldFirst.previous = newLink;
        size++;
        modCount++;
        return true;
    }

添加尾部源码解析

 public void addLast(E object) {
        addLastImpl(object);
    }

private boolean addLastImpl(E object) { 
          //在构造函数的时候我们进行了二分查找,此时是倒查找
        Link<E> oldLast = voidLink.previous;//此时指向的是最后一个指针
        Link<E> newLink = new Link<E>(object, oldLast, voidLink);
        voidLink.previous = newLink;
        oldLast.next = newLink;
        size++;
        modCount++;
        return true;
    }

是否有上下指针

  public boolean hasNext() { 
            return link.next != list.voidLink;//不等于头指针就代表有下个指针
 }
 public boolean hasPrevious() {
            return link != list.voidLink;
}

next源码解析

       public ET next() {
            if (expectedModCount == list.modCount) {
                LinkedList.Link<ET> next = link.next;
                if (next != list.voidLink) {//代表有下一个
                    lastLink = link = next;//默认这是最后一个指针和正处于的指针都为下一个指向的指针
                    pos++;
                    return link.data;//返回数据
                }
                throw new NoSuchElementException();
            }
            throw new ConcurrentModificationException();
        }

移除源码解析

public void remove() {
            if (expectedModCount == list.modCount) {
                if (lastLink != null) {
                     Link<ET> next = lastLink.next; //next 最后节点下一个指针03
                    Link<ET> previous = lastLink.previous;//previous  最后节点上一个指针01
                    next.previous = previous;// next.previous为03的前一个指针指向01
                    previous.next = next;// previous.next 01的下一个指针指向03
                    if (lastLink == link) {
                        pos--;
                    }
                    link = previous;
                    lastLink = null;
                    expectedModCount++;
                    list.size--;
                    list.modCount++;
                } else {
                    throw new IllegalStateException();
                }
            } else {
                throw new ConcurrentModificationException();
            }
        }

补充一下,简单看下LinkedHashMap双向循环列表的add源码


 @Override void addNewEntry(K key, V value, int hash, int index) {
        LinkedEntry<K, V> header = this.header;//首先获取头部

        LinkedEntry<K, V> eldest = header.nxt;
        if (eldest != header && removeEldestEntry(eldest)) {
            remove(eldest.key);
        }
        LinkedEntry<K, V> oldTail = header.prv;//头部指向前一个指针即最后一个元素
        LinkedEntry<K, V> newTail = new LinkedEntry<K,V>(
                key, value, hash, table[index], header, oldTail);//new一个新的指针
           //头部前一个指向新的指针,原本最后一个元素的下一个指针指向新的指针
        table[index] = oldTail.nxt = header.prv = newTail;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值