LinkedList复习
LinkedList复习
数据结构
LinkedList本质上是一个双向列表,节点的数据表结构如下
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;
}
}
构造函数
public LinkedList() {
}
/**
* Constructs a list containing the elements of the specified
* collection, in the order they are returned by the collection's
* iterator.
*
* @param c the collection whose elements are to be placed into this list
* @throws NullPointerException if the specified collection is null
*/
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}
有参构造的addAll函数
public boolean addAll(Collection<? extends E> c) {
return addAll(size, c);
}
调用的addAll函数,添加多个元素
/**
* Inserts all of the elements in the specified collection into this
* list, starting at the specified position. Shifts the element
* currently at that position (if any) and any subsequent elements to
* the right (increases their indices). The new elements will appear
* in the list in the order that they are returned by the
* specified collection's iterator.
*
* @param index index at which to insert the first element
* from the specified collection
* @param c collection containing elements to be added to this list
* @return {@code true} if this list changed as a result of the call
* @throws IndexOutOfBoundsException {@inheritDoc}
* @throws NullPointerException if the specified collection is null
*/
public boolean addAll(int index, Collection<? extends E> c) {
//确保范围在0-index之间
checkPositionIndex(index);
//转为数组
Object[] a = c.toArray();
int numNew = a.length;
if (numNew == 0)
return false;
//获取插入位置的前后节点
Node<E> pred, succ;
if (index == size) {
//如果插入位置在最后
succ = null;
pred = last;
} else {
succ = node(index);
pred = succ.prev;
}
//循环插入节点
for (Object o : a) {
@SuppressWarnings("unchecked") E e = (E) o;
//pred指针有了
Node<E> newNode = new Node<>(pred, e, null);
//如果插入的位置是头部
if (pred == null)
first = newNode;
else
//补上next指针
pred.next = newNode;
pred = newNode;
}
if (succ == null) {
//如果插入的位置是最后
last = pred;
} else {
//将新插入的链表和旧的链表连接接起来
pred.next = succ;
succ.prev = pred;
}
size += numNew;
modCount++;
return true;
}
add方法
boolean add(E e)
public boolean add(E e) {
linkLast(e);
return true;
}
调用的方法LinkLast
void linkLast(E e) {
final Node<E> l = last;
//pred指针赋值
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
//如果链表为空
if (l == null)
first = newNode;
else
//补上next指针
l.next = newNode;
size++;
modCount++;
}
void add(int index, E element)
public void add(int index, E element) {
//检查索引
checkPositionIndex(index);
if (index == size)
//插入的位置在最后
linkLast(element);
else
//插入的位置在中间
linkBefore(element, node(index));
}
方法linkBefore
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++;
}
获取数据的方法
E get(int index)
public E get(int index) {
//检查index范围是否在size之内
checkElementIndex(index);
//调用Node(index)去找到index对应的node然后返回它的值
return node(index).item;
}
获取头节点
区别在于对链表为空时的处理,是抛出异常还是返回null,其中getFirst() 和element() 方法将会在链表为空时,抛出异常
public E getFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return f.item;
}
public E element() {
return getFirst();
}
public E peek() {
final Node<E> f = first;
return (f == null) ? null : f.item;
}
public E peekFirst() {
final Node<E> f = first;
return (f == null) ? null : f.item;
}
获取尾节点
public E getLast() {
final Node<E> l = last;
if (l == null)
throw new NoSuchElementException();
return l.item;
}
public E peekLast() {
final Node<E> l = last;
return (l == null) ? null : l.item;
}
根据对象得到索引
从头找
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 lastIndexOf(Object o) {
int index = size;
if (o == null) {
//从尾遍历
for (Node<E> x = last; x != null; x = x.prev) {
index--;
if (x.item == null)
return index;
}
} else {
//从尾遍历
for (Node<E> x = last; x != null; x = x.prev) {
index--;
if (o.equals(x.item))
return index;
}
}
return -1;
}
检查链表是否包含对象
public boolean contains(Object o) {
return indexOf(o) != -1;
}
删除方法
删除头节点
public E pop() {
return removeFirst();
}
public E remove() {
return removeFirst();
}
public E removeFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return unlinkFirst(f);
}
删除尾节点
public E removeLast() {
final Node<E> l = last;
if (l == null)
throw new NoSuchElementException();
return unlinkLast(l);
}
public E pollLast() {
final Node<E> l = last;
return (l == null) ? null : unlinkLast(l);
}
删除指定节点
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;
}
unlink方法
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;
}
删除指定索引节点
public E remove(int index) {
//检查index范围
checkElementIndex(index);
//将节点删除
return unlink(node(index));
}
删除最后的节点
private E unlinkLast(Node<E> l) {
// assert l == last && l != null;
final E element = l.item;
final Node<E> prev = l.prev;
//删除最后的节点
l.item = null;
l.prev = null; // help GC
//改变last节点
last = prev;
//如果只有一个节点
if (prev == null)
first = null;
else
//将删除节点的后继指针改为空
prev.next = null;
size--;
modCount++;
return element;
}