Skip to content

Instantly share code, notes, and snippets.

@ClickerMonkey
Created November 18, 2013 20:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ClickerMonkey/7534505 to your computer and use it in GitHub Desktop.
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.
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();
}
}
}
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