Created
November 18, 2013 20:11
-
-
Save ClickerMonkey/7534505 to your computer and use it in GitHub Desktop.
Doubly linked-list where nodes can remove themselves instantly from their list. A node can only be in one list. O(1) adding and removal.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class LinkedList<T> implements Iterable<T> | |
{ | |
public LinkedNode<T> head = new LinkedNode<T>( this ); | |
private int size = 0; | |
public final LinkedNode<T> add( T value ) | |
{ | |
return new LinkedNode<T>( value ).prepend( head ); | |
} | |
public final LinkedNode<T> pushFront( T value ) | |
{ | |
return new LinkedNode<T>( value ).append( head ); | |
} | |
public final LinkedNode<T> pushBack( T value ) | |
{ | |
return new LinkedNode<T>( value ).prepend( head ); | |
} | |
public final LinkedNode<T> insertAfter( T value, int index ) | |
{ | |
return internalInsert( new LinkedNode<T>( value ), getNode( index ) ); | |
} | |
public final LinkedNode<T> insertAfter( T value, T afterValue ) | |
{ | |
return internalInsert( new LinkedNode<T>( value ), getNode( afterValue ) ); | |
} | |
public final LinkedNode<T> set( int index, T value ) | |
{ | |
return internalSet( value, getNode( index ) ); | |
} | |
public final LinkedNode<T> set( T oldValue, T newValue ) | |
{ | |
return internalSet( newValue, getNode( oldValue ) ); | |
} | |
public final LinkedNode<T> getNode( T value ) | |
{ | |
LinkedNode<T> n = head.next; | |
while (n != head) | |
{ | |
if (n.value == value || (value != null && value.equals( n.value ))) | |
{ | |
return n; | |
} | |
n = n.next; | |
} | |
return null; | |
} | |
public final LinkedNode<T> getNode( int index ) | |
{ | |
if (index < 0 || index >= size) | |
{ | |
return null; | |
} | |
LinkedNode<T> n = head.next; | |
while (--index >= 0) | |
n = n.next; | |
return n; | |
} | |
public final T get( T value ) | |
{ | |
return getValue( getNode( value ) ); | |
} | |
public final T get( int index ) | |
{ | |
return getValue( getNode( index ) ); | |
} | |
public final T remove( T value ) | |
{ | |
return getValue( internalRemove( getNode( value ) ) ); | |
} | |
public final LinkedNode<T> removeNode( T value ) | |
{ | |
return internalRemove( getNode( value ) ); | |
} | |
public final T remove( int index ) | |
{ | |
return getValue( internalRemove( getNode( index ) ) ); | |
} | |
public final LinkedNode<T> removeNode( int index ) | |
{ | |
return internalRemove( getNode( index ) ); | |
} | |
public final void clear() | |
{ | |
while (head.next != head) | |
{ | |
head.next.remove(); | |
} | |
} | |
private final T getValue( LinkedNode<T> n ) | |
{ | |
return (n == null ? null : n.value); | |
} | |
private final LinkedNode<T> internalRemove( LinkedNode<T> node ) | |
{ | |
return (node == null ? null : node.remove()); | |
} | |
private final LinkedNode<T> internalInsert( LinkedNode<T> node, LinkedNode<T> after ) | |
{ | |
return (after == null ? null : node.append( after )); | |
} | |
private final LinkedNode<T> internalSet( T value, LinkedNode<T> node ) | |
{ | |
return (node == null ? null : node.set( value )); | |
} | |
public final LinkedNode<T> popFrontNode() | |
{ | |
return (size == 0 ? null : head.next.remove()); | |
} | |
public final T popFront() | |
{ | |
return (size == 0 ? null : head.next.remove().value); | |
} | |
public final LinkedNode<T> popBackNode() | |
{ | |
return (size == 0 ? null : head.prev.remove()); | |
} | |
public final T popBack() | |
{ | |
return (size == 0 ? null : head.prev.remove().value); | |
} | |
public final LinkedNode<T> peekFrontNode() | |
{ | |
return (size == 0 ? null : head.next); | |
} | |
public final T peekFront() | |
{ | |
return (size == 0 ? null : head.next.value); | |
} | |
public final LinkedNode<T> peekBackNode() | |
{ | |
return (size == 0 ? null : head.prev); | |
} | |
public final T peekBack() | |
{ | |
return (size == 0 ? null : head.prev.value); | |
} | |
protected final void onRemove( LinkedNode<T> node ) | |
{ | |
size--; | |
} | |
protected final void onAdd( LinkedNode<T> node ) | |
{ | |
size++; | |
} | |
public final LinkedNode<T> head() | |
{ | |
return head; | |
} | |
public final int size() | |
{ | |
return size; | |
} | |
public final boolean isEmpty() | |
{ | |
return (size == 0); | |
} | |
public final boolean hasValues() | |
{ | |
return (size > 0); | |
} | |
public final Iterator<T> iterator() | |
{ | |
return new LinkedListIterator<T>( head ); | |
} | |
private class LinkedListIterator<E> implements Iterator<E> | |
{ | |
private LinkedNode<E> node; | |
private LinkedNode<E> next; | |
public LinkedListIterator( LinkedNode<E> head ) | |
{ | |
this.node = head; | |
this.next = head.next; | |
} | |
public boolean hasNext() | |
{ | |
return (next != head); | |
} | |
public E next() | |
{ | |
node = next; | |
next = node.next; | |
return node.value; | |
} | |
public void remove() | |
{ | |
node.remove(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class LinkedNode<T> | |
{ | |
public T value; | |
protected LinkedList<T> list; | |
protected LinkedNode<T> next; | |
protected LinkedNode<T> prev; | |
public LinkedNode( T value ) | |
{ | |
this.value = value; | |
} | |
protected LinkedNode( LinkedList<T> list ) | |
{ | |
this.list = list; | |
this.next = this.prev = this; | |
} | |
public boolean inList() | |
{ | |
return (list != null); | |
} | |
public LinkedNode<T> remove() | |
{ | |
if (list != null && list.head != this) | |
{ | |
next.prev = prev; | |
prev.next = next; | |
list.onRemove( this ); | |
prev = next = null; | |
list = null; | |
} | |
return this; | |
} | |
public LinkedNode<T> append( LinkedNode<T> node ) | |
{ | |
return insert( node, node.next ); | |
} | |
public LinkedNode<T> prepend( LinkedNode<T> node ) | |
{ | |
return insert( node.prev, node ); | |
} | |
public LinkedNode<T> next() | |
{ | |
return next; | |
} | |
public LinkedNode<T> prev() | |
{ | |
return prev; | |
} | |
protected LinkedNode<T> insert( LinkedNode<T> p, LinkedNode<T> n ) | |
{ | |
if (list == null || list.head != this) | |
{ | |
remove(); | |
(next = n).prev = (prev = p).next = this; | |
(list = n.list).onAdd( this ); | |
return this; | |
} | |
return null; | |
} | |
protected LinkedNode<T> set( T value ) | |
{ | |
this.value = value; | |
return this; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment