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

线性表:顺序存储结构和链式存储结构
链式存储结构的优缺点:

  • 优点:删除插入效率高
  • 缺点:查询效率高


    链式存储方式线性表之LinkedList源码解析_第1张图片
    image.png

    链式存储方式线性表之LinkedList源码解析_第2张图片
    image.png

    循环列表:将单链表中终端结点的指针端由空指针改为指向头结点,就使整个单链表形成一个环,这种头尾相连的单链表称为单循环链表,简称循环链表


    image.png

    双向循环列表:双向循环链表是单向循环链表的每个结点中,再设置一个指向其前驱结点的指针域
    链式存储方式线性表之LinkedList源码解析_第3张图片
    image.png

    对于空的双向循环列表
    链式存储方式线性表之LinkedList源码解析_第4张图片
    image.png

    双向循环列表插入


    链式存储方式线性表之LinkedList源码解析_第5张图片
    image.png

    双向列表的删除
    链式存储方式线性表之LinkedList源码解析_第6张图片
    image.png

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

参数和构造函数源码解析

transient Link voidLink;//这个参数代表头指针

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

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

        Link(ET o, Link p, Link n) {
            data = o;
            previous = p;
            next = n;
        }
    }

迭代器源码解析

参数和构造函数源码解析

  private static final class LinkIterator implements ListIterator {
       final LinkedList list;
        Link link, lastLink;//当前节点和最后一个节点
 //双向列表
  LinkIterator(LinkedList 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 next = link.next;//原本指向的下一个节点
             //添加对象新建一个节点     link为前一个节点,next为下一个节点
              Link newLink = new Link(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 oldFirst = voidLink.next;//原本指向01
        Link newLink = new Link(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 oldLast = voidLink.previous;//此时指向的是最后一个指针
        Link newLink = new Link(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 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 next = lastLink.next; //next 最后节点下一个指针03
                   Link 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 header = this.header;//首先获取头部

        LinkedEntry eldest = header.nxt;
        if (eldest != header && removeEldestEntry(eldest)) {
            remove(eldest.key);
        }
        LinkedEntry oldTail = header.prv;//头部指向前一个指针即最后一个元素
        LinkedEntry newTail = new LinkedEntry(
                key, value, hash, table[index], header, oldTail);//new一个新的指针
           //头部前一个指向新的指针,原本最后一个元素的下一个指针指向新的指针
        table[index] = oldTail.nxt = header.prv = newTail;
    }

你可能感兴趣的:(链式存储方式线性表之LinkedList源码解析)