package com.coding.basic;
import java.util.NoSuchElementException;
public class DoubleNodeLinkedList<E> implements List<E> {
private int size = 0;
private Node<E> first;
private Node<E> last;
public void add(E o){
add(size,o);
}
public void add(int index , E o){
rangeCheck(index);
if(index == size){
linkLast(o);
}else{
linkBefore(o, indexOf(index));
}
}
private void linkBefore(E o ,Node<E> succ){
final Node<E> prev = succ.prev;
final Node<E> newNode = new Node<E>(prev, o, succ);
succ.prev = newNode;
if(prev == null){
first = newNode;
}else{
prev.next = newNode;
}
size++;
}
private void linkLast(E o){
final Node<E> succ = last;
final Node<E> newNode = new Node<E>(succ, o, null);
last = newNode;
if(succ == null){
first = newNode;
}else{
succ.next = newNode;
}
size++;
}
/**
* range check,
* permit the range [0,size]
* @param index
*/
private void rangeCheck(int index) {
if(index > size|| index < 0 )
throw new IndexOutOfBoundsException("Size"+size+":index"+index);
}
/**
* element's index check,
* permit the index [0,size)
* @param index
*/
private void elementIndexCheck(int index){
if(index >=size||index < 0)
throw new IndexOutOfBoundsException("Size"+size+":index"+index);
}
/**
*
* @param index
* @return
*/
private Node<E> indexOf(int index){
if(index < (this.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 = this.size-1; i > index; i--) {
x = x.prev;
}
return x;
}
}
public E get(int index){
elementIndexCheck(index);
return indexOf(index).data;
}
public E remove(int index){
elementIndexCheck(index);
if(index == 0){
return removeFirst();
}else if(index == size) {
return removeLast();
}else{
return unlinkNode(indexOf(index));
}
}
private E unlinkNode(Node<E> node) {
final Node<E> next = node.next;
final Node<E> prev = node.prev;
final E element = node.data;
if(next == null){
last = node;
}else{
next.prev = node;
node.next = next;
}
if(prev == null){
first = node;
}else{
prev.next = node;
node.prev = prev;
}
size--;
node.data = null;
return element;
}
public int size(){
return size;
}
public void addFirst(E o){
linkBefore(o, first);
}
public void addLast(E o){
linkLast(o);
}
public E removeFirst(){
if(first == null)
throw new NoSuchElementException("first is null");
E oldData = first.data;
final Node<E> next = first.next;
first.data = null;
first.next = null;//GC
first = next;
if(next == null){
last = null;
}else{
next.prev = null;
}
size--;
return oldData;
}
public E removeLast(){
if(last == null)
throw new NoSuchElementException("last is null");
E oldData = last.data;
final Node<E> prev = last.prev;
last.prev = null;
last.data = null;//GC
last = prev;
if(prev == null){
first = null;
}else{
prev.next = null;
}
size--;
return oldData;
}
public Iterator iterator(){
return null;
}
private static class Node<E>{
E data;
Node<E> next;
Node<E> prev;
Node(Node<E> prev,E data,Node<E> next){
this.data = data;
this.next = next;
this.prev = prev;
}
}
}