package org.wsc.coding.basic.list;
import java.util.ConcurrentModificationException;
import java.util.NoSuchElementException;
/**
* LinkedList类
* 实现List接口和Queue接口
* 基于链表的集合
* @author Administrator
* @date 2017年2月25日上午10:52:41
* @version v1.0
*
* @param <E>
*/
public class LinkedList<E> implements List<E>,Queue<E> {
private int size;
Node<E> first; // 链表的头节点
Node<E> last; // 链表的尾节点
private static class Node<E> {
E item; // 存储数据
Node<E> prev; // 上一个节点
Node<E> next; // 下一个节点
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
@Override
public int size() {
return size;
}
@Override
public boolean isEmpty() {
return size == 0;
}
@Override
public Iterator<E> iterator() {
return new Itr();
}
private class Itr implements Iterator<E> {
int cursor; // 当前索引
int lastRet = -1;// 上一次索引
@Override
public boolean hasNext() {
return cursor != size;
}
@Override
public E next() {
if (cursor > size) {
throw new NoSuchElementException();
}
return get(lastRet = cursor++);
}
@Override
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
try {
LinkedList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
size--;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
}
@Override
public boolean add(E e) {
linkLast(e);
return true;
}
@Override
public boolean add(int index, E element) {
checkPositionIndex(index);// 位置范围检查
// 如果索引等于元素个数,则直接插入尾部
if (index == size) {
linkLast(element);
} else {
linkBefore(element, node(index));
}
return true;
}
@Override
public E get(int index) {
return node(index).item;
}
/**
* 维护头节点
*
* @param e
*/
void linkFirst(E e) {
Node<E> f = first;
// 创建新节点,将原头节点作为新节点的下一个节点
Node<E> newNode = new Node<E>(null, e, f);
// 将新节点设置为头节点
first = newNode;
// 如原头节点为null,则尾节点也为newNode
if (f == null) {
last = newNode;
} else {// 否则将新节点作为原头节点的上一个节点
f.prev = newNode;
}
size++;
}
/**
* 维护尾节点
*
* @param e
*/
void linkLast(E e) {
Node<E> l = last;
// 创建新节点,将尾节点作为新节点的上一个节点
Node<E> newNode = new Node<E>(l, e, null);
// 将新节点设置为尾节点
last = newNode;
// 如原尾节点为null,则头节点也为newNode
if (l == null) {
first = newNode;
} else {// 否则将新节点作为原尾节点的下一个节点
l.next = newNode;
}
size++;
}
/**
* 在指定节点前插入新节点
*
* @param e
* @param node
*/
void linkBefore(E e, Node<E> node) {
// 获取node的上一个节点,并创建新节点,将pred做为新节点的上一个节点,将node作为新节点的下一个节点
final Node<E> pred = node.prev;
final Node<E> newNode = new Node<>(pred, e, node);
// 将node的上一个节点指向newNode
node.prev = newNode;
// 如prev为null,则说明node为first,那么将新节点设为first
if (pred == null) {
first = newNode;
} else {// 否则,将新节点设为pred的下一个节点
pred.next = newNode;
}
size++;
}
/**
* 获取节点
*
* @param index
* @return
*/
Node<E> node(int index) {
// 索引小于长度的2分之一则从前向后遍历,否则从后向前遍历,减少遍历次数
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;
}
}
/**
* 获取头节点
*
* @return
*/
public E getFirst() {
Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return f.item;
}
/**
* 获取尾节点
*
* @return
*/
public E getLast() {
Node<E> l = last;
if (l == null)
throw new NoSuchElementException();
return l.item;
}
@Override
public E set(int index, E e) {
checkElementIndex(index);// 索引范围检查
// 获取索引处节点,填入新值,返回原值
Node<E> x = node(index);
E oldVal = x.item;
x.item = e;
return oldVal;
}
@Override
public E remove(int index) {
checkElementIndex(index);// 索引范围检查
return unlink(node(index));
}
public E removeFirst() {
//获取头节点
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return remove(0);
}
/**
* 删除节点
*
* @param x
* @return
*/
E unlink(Node<E> x) {
// 获取此节点的上一个节点和下一个节点
E element = x.item;
Node<E> prev = x.prev;
Node<E> next = x.next;
// 如prev节点为null,则说明x节点为first,那么将next节点设为first
if (prev == null) {
first = next;
} else {// 否则,将prev节点的下一个节点设为next
prev.next = next;
}
// 如next节点为null,则说明x节点为last,那么将prev节点设为last
if (next == null) {
last = prev;
} else {// 否则,将next节点的上一个节点设为prev
next.prev = prev;
}
x.item = null;
size--;
return element;
}
@Override
public void enQueue(E e) {
linkLast(e);
}
@Override
public E deQueue() {
return removeFirst();
}
/**
* 位置范围检查 >0 && <=size
*
* @param index
*/
private void checkPositionIndex(int index) {
if (index > this.size || index < 0)// 添加可以往末位插入,所以这里索引等于元素个数也可以
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
/**
* 索引范围检查 >0 && <size
*
* @param index
*/
private void checkElementIndex(int index) {
if (index < 0 || index >= this.size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
/**
* 以字符串形式返回索引和元素个数信息
*
* @param index
* @return
*/
private String outOfBoundsMsg(int index) {
return "Index: " + index + ", Size: " + this.size;
}
@Override
public E[] toArray() {
// TODO Auto-generated method stub
return null;
}
@Override
public <T> T[] toArray(T[] a) {
// TODO Auto-generated method stub
return null;
}
}