LinkedList源码笔记
来源:互联网 发布:修改软件下载 编辑:程序博客网 时间:2024/06/08 07:16
链表结构
不同于数组与向量中各数据项的物理存放位置与逻辑次序完全对应,链表中的元素虽然也构成一个线性逻辑次序,但其元素的物理地址可以任意。
链表中的元素维护一个前驱与后继,分别指向上一个元素与下一个元素的地址。
头尾节点与首末节点
链表结构中,除了可见的首末节点first、last,还有不可见的头尾节点header、trailer。
创建链表时即创建头尾节点,first时头节点的后继,last是尾节点的前驱。这种设计方法使得相关算法不必再对各种边界退化情况做专门处理。
Java中对链表的实现LinkedList
LinkedList中实现了一个内部私有类,其中next指向下一个节点,prev指向前一个节点,item是当前节点的值
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.next = next; this.prev = prev; } }
另外还有两个内部私有变量size与modCount。
其中modCount用于记录LinkedList被修改的次数。
LinkedList提供两个构造方法
public LinkedList() {}public LinkedList(Collection<? extends E> c) { this(); addAll(c);}
LinkedList添加元素
在首次创建LinkedList时调用add(E e)函数,last == first == null。
将新创建的节点前驱指向LinkedList的last,即指向头节点null。
新节点newNode(l,e,null),将l即最后一个节点作为前驱,此时指向null。null作为后继,即指向不可见的尾节点,值为e。
将LinkedLits的last 指向新创建的节点。
满足 l == null,将LinkedList的first指向该节点。
此时列表中只有一个节点和隐含的两个不可见的头尾节点。
在LinkedList已有元素时调用add(E e),last指向最后一个节点,first指向第一个节点。
l = last 指向最后一个节点。
新节点newNode(l,e,null),将l即最后一个节点作为前驱。null作为后继,即指向不可见的尾节点,值为e。
将LinkedList的last替换为新节点newNode。
l != null,不满足条件语句将l的后继替换成新节点newNode,不再指向null。
public boolean add(E e) { linkLast(e); return true;}void linkLast(E e) { final Node<E> l = last; final Node<E> newNode = new Node<>(l, e, null); last = newNode; if (l == null) first = newNode; else l.next = newNode; size++; modCount++;}
在指定的索引处添加元素
当index == size,将e作为最后一个节点链接。
当index != size,将新节点(值为e)插入index的位置。node(index)的前驱作为新节点的前驱,node(index)作为新节点的后继。
public void add(int index, E element) { checkPositionIndex(index);//对index进行有效性判定 if (index == size) linkLast(element); else linkBefore(element, node(index)); } /** * Links e as last element. */ void linkLast(E e) { final Node<E> l = last; final Node<E> newNode = new Node<>(l, e, null); last = newNode; if (l == null) first = newNode; else l.next = newNode; size++; modCount++; } /** * Inserts element e before non-null Node succ. */ void linkBefore(E e, Node<E> succ) { // assert succ != null; final Node<E> pred = succ.prev; final Node<E> newNode = new Node<>(pred, e, succ); succ.prev = newNode; if (pred == null) first = newNode; else pred.next = newNode; size++; modCount++; } /** * Returns the (non-null) Node at the specified element index. */ Node<E> node(int index) { // assert isElementIndex(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 E remove() { return removeFirst(); } public E removeFirst() { final Node<E> f = first; if (f == null) throw new NoSuchElementException(); return unlinkFirst(f); } private E unlinkFirst(Node<E> f) { // assert f == first && f != null; final E element = f.item; final Node<E> next = f.next; f.item = null; f.next = null; // help GC first = next; if (next == null) last = null; else next.prev = null; size--; modCount++; return element; }
清除整个节点
public void clear() { // Clearing all of the links between nodes is "unnecessary", but: // - helps a generational GC if the discarded nodes inhabit // more than one generation // - is sure to free memory even if there is a reachable Iterator for (Node<E> x = first; x != null; ) { Node<E> next = x.next; x.item = null; x.next = null; x.prev = null; x = next; } first = last = null; size = 0; modCount++; }
- LinkedList源码阅读笔记
- LinkedList源码笔记
- LinkedList源码阅读笔记
- LinkedList<E>源码学习笔记
- jdk源码学习笔记--LinkedList
- ArrayList和LinkedList源码阅读笔记
- Java集合源码阅读笔记-LinkedList
- JDK1.7源码笔记之LinkedList类
- LinkedList源码
- LinkedList源码
- LinkedList源码
- LinkedList源码
- LinkedList笔记
- LinkedList笔记
- 【源码】LinkedList源码剖析
- JDK源码-LinkedList源码
- JAVA 集合类(java.util)源码阅读笔记------LinkedList
- LinkedList 源码分析
- 浅谈this指针
- 内存取证——文件
- python-配置pip源
- 学习笔记TF058:人脸识别
- linux虚拟机IP配置及SVN服务环境搭建
- LinkedList源码笔记
- 大数据(三十一)HBASE【Hbase Shell 常用命令】
- 内存漫谈
- 人脸检测——DDFD
- [Java读书笔记]之Swing
- [学习笔记] 树状数组区间加+区间求和
- 整数全排列问题
- 不同的路径
- 给定一个链表,一次颠倒链表k的节点并返回其修改列表。如果节点的数量不是k的倍数,那末最后的剩余节点应该保持原样。