LinkedList
一、LinkedList是什么?
LinkedList是基于双向链表实现的一种数据结构
二、LinkedList的实现
1.LinkedList说明
代码如下(示例):
/**
* Doubly-linked list implementation of the {@code List} and {@code Deque}
* interfaces. Implements all optional list operations, and permits all
* elements (including {@code null}).
*
双向链表实现的LinkedList,可以存储任何数据类型,包括null。提到双向链表,就要提到单向链表,相较于单向链表,为什么LinkedList使用的是双向链表,单向链表使用的空间较少,但是对一些操作不太方便,双向链表的则是使用的空间大点,但是对数据的操作更方便点。(例如一般只能在链表的开始或结束插入,否则时间复杂度则为O(N),而双向链表无论开始或结束插入,时间复杂度皆为O(1),因为有前后两个节点)
2.Node
代码如下(示例):
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;
}
}
这个是其静态内部类,为什么要使用静态内部类呢,我的理解是经常用到的类,或是要访问其外部静态变量或静态方法的时候会使用静态内部类。static静态关键字及加载时的情况可以在之后的JVM的学习中继续研究。
2.Add()
/**
* Appends the specified element to the end of this list.
*
* <p>This method is equivalent to {@link #addLast}.
*
* @param e element to be appended to this list
* @return {@code true} (as specified by {@link Collection#add})
*/
public boolean add(E e) {
linkLast(e);
return true;
}
/**
* Inserts the specified element at the specified position in this list.
* Shifts the element currently at that position (if any) and any
* subsequent elements to the right (adds one to their indices).
*
* @param index index at which the specified element is to be inserted
* @param element element to be inserted
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public void add(int index, E element) {
checkPositionIndex(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;
}
}
也即是add()这个方法的两种方法,一个是指定了位置index,一个是只添加元素的方法,其中add会直接把元素链接到链表的最后面,而另一种则是,如果其大小为其元素数量这是链接到最后,否则则是在目标元素前链接该元素。其中checkPositionIndex(index);方法以及用到较多的node(int index),的设计写法可以学习下。且其中node(int index)寻找方法也更快捷些,如果index值小于size/2者从头开始遍历,反之从后面开始遍历,这样时间复杂度应为O(N/2)
2.indexOf()
/**
* Returns the index of the first occurrence of the specified element
* in this list, or -1 if this list does not contain the element.
* More formally, returns the lowest index {@code i} such that
* <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>,
* or -1 if there is no such index.
*
* @param o element to search for
* @return the index of the first occurrence of the specified element in
* this list, or -1 if this list does not contain the element
*/
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;
}
indexOf即寻找一元素的方法,其对应元素是否为空的两种情况分别做了处理,此方法时间复杂度为O(N)
3.remove()
/**
* Removes the first occurrence of the specified element from this list,
* if it is present. If this list does not contain the element, it is
* unchanged. More formally, removes the element with the lowest index
* {@code i} such that
* <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>
* (if such an element exists). Returns {@code true} if this list
* contained the specified element (or equivalently, if this list
* changed as a result of the call).
*
* @param o element to be removed from this list, if present
* @return {@code true} if this list contained the specified element
*/
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;
}
/**
* Unlinks non-null node x.
*/
E unlink(Node<E> x) {
// assert x != null;
final E element = x.item;
final Node<E> next = x.next;
final Node<E> prev = x.prev;
if (prev == null) {
first = next;
} else {
prev.next = next;
x.prev = null;
}
if (next == null) {
last = prev;
} else {
next.prev = prev;
x.next = null;
}
x.item = null;
size--;
modCount++;
return element;
}
remove()相当于删除第一个元素,指定了object的remov(Obect o)则是相当于遍历,找到此节点,然后删除此节点。删除节点时有分为了是否首尾节点,分别处理。
4.get()等
总结
暂时先看这些常用的方法,后面的方法会继续学习