package com.github.congcongcong250.coding2017.basic;
import java.util.NoSuchElementException;
public class WLinkedList implements WList {
private Node head;
private int size;
public WLinkedList(){
head = new Node();
size = 0;
}
public void add(Object o){
addLast(o);
}
public void add(int index , Object o){
//Check bound
checkIndex(index);
Node nx = this.find(index);
Node pr = nx.previous;
Node in = new Node(o,pr,nx);
nx.previous = in;
pr.next = in;
size++;
}
public Object get(int index){
//Check bound
checkIndex(index);
return this.find(index).data;
}
public Object remove(int index){
//Check bound
checkIndex(index);
Node rem = this.find(index);
Node pr = rem.previous;
Node nx = rem.next;
pr.next = nx;
nx.previous = pr;
Object ret = rem.data;
rem.previous = null;
rem.next = null;
rem.data = null;
size--;
return ret;
}
public int size(){
return size;
}
public void addFirst(Object o){
Node nx = head.next;
Node in = new Node(o,head, nx);
head.next = in;
nx.previous = in;
size++;
}
public void addLast(Object o){
Node last = head.previous;
Node in = new Node(o,last,head);
last.next = in;
head.previous = in;
size++;
}
public Object removeFirst(){
return remove(0);
}
public Object removeLast(){
return remove(size-1);
}
public WIterator wIterator(){
return new ListItr();
}
public void clear(){
for (Node x = head; x != null; ) {
Node next = x.next;
x.data = null;
x.next = null;
x.previous = null;
x = next;
}
}
private void checkIndex(int index){
if(index >= size || index < 0){
throw new IndexOutOfBoundsException("Index:"+index+" Size:"+size);
}
}
private Node find(int index){
Node tra = head;
//If index < size/2
if( index < (size >> 1)){
for(int i = 0; i <= index; i++){
tra = tra.next;
}
}else{
for(int i = size; i > index; i--){
tra = tra.previous;
}
}
return tra;
}
private static class Node{
Object data;
Node next;
Node previous;
public Node(){
data = null;
next = this;
previous = this;
}
public Node(Object obj,Node pre, Node nx){
data = obj;
next = nx;
previous = pre;
}
}
private class ListItr implements WIterator{
//Point to next node
Node cursor;
int nextIndex;
public ListItr(){
cursor = head.next;
nextIndex = 0;
}
@Override
public boolean hasNext() {
return nextIndex < size;
}
@Override
public Object next() {
checkBound();
Node re = cursor;
cursor = cursor.next;
nextIndex++;
return re.data;
}
public Object previous() {
Node re = cursor.previous.previous;
cursor = cursor.previous;
nextIndex--;
return re.data;
}
@Override
public void remove() {
//Check bound
checkBound();
WLinkedList.this.remove(--nextIndex);
}
private void checkBound(){
if(nextIndex >= size){
throw new NoSuchElementException("Iterates to the end");
}
}
}
}