programming-examples/java/Data_Structures/List.java
2019-11-15 12:59:38 +01:00

1071 lines
27 KiB
Java

package com.jwetherell.algorithms.data_structures;
import java.util.Arrays;
import com.jwetherell.algorithms.data_structures.interfaces.IList;
@SuppressWarnings("unchecked")
public abstract class List<T> implements IList<T> {
/**
* A dynamic array, growable array, resizable array, dynamic table, or array
* list is a random access, variable-size list data structure that allows
* elements to be added or removed.
*
* http://en.wikipedia.org/wiki/Dynamic_array
*
* @author Justin Wetherell <phishman3579@gmail.com>
*/
public static class ArrayList<T> extends List<T> {
private static final int MINIMUM_SIZE = 1024;
private int size = 0;
private T[] array = (T[]) new Object[MINIMUM_SIZE];
/**
* {@inheritDoc}
*/
@Override
public boolean add(T value) {
return add(size,value);
}
/**
* Add value to list at index.
*
* @param index to add value.
* @param value to add to list.
*/
public boolean add(int index, T value) {
if (size >= array.length)
grow();
if (index==size) {
array[size] = value;
} else {
// Shift the array down one spot
System.arraycopy(array, index, array, index+1, size - index);
array[index] = value;
}
size++;
return true;
}
/**
* {@inheritDoc}
*/
@Override
public boolean remove(T value) {
for (int i = 0; i < size; i++) {
T obj = array[i];
if (obj.equals(value)) {
if (remove(i)!=null) return true;
return false;
}
}
return false;
}
/**
* Remove value at index from list.
*
* @param index of value to remove.
* @return value at index.
*/
public T remove(int index) {
if (index<0 || index>=size) return null;
T t = array[index];
if (index != --size) {
// Shift the array down one spot
System.arraycopy(array, index + 1, array, index, size - index);
}
array[size] = null;
int shrinkSize = array.length>>1;
if (shrinkSize >= MINIMUM_SIZE && size < shrinkSize)
shrink();
return t;
}
// Grow the array by 50%
private void grow() {
int growSize = size + (size<<1);
array = Arrays.copyOf(array, growSize);
}
// Shrink the array by 50%
private void shrink() {
int shrinkSize = array.length>>1;
array = Arrays.copyOf(array, shrinkSize);
}
/**
* Set value at index.
*
* @param index of value to set.
* @param value to set.
* @return value previously at index.
*/
public T set(int index, T value) {
if (index<0 || index>=size) return null;
T t = array[index];
array[index] = value;
return t;
}
/**
* Get value at index.
*
* @param index of value to get.
* @return value at index.
*/
public T get(int index) {
if (index<0 || index>=size) return null;
return array[index];
}
/**
* {@inheritDoc}
*/
@Override
public void clear() {
size = 0;
}
/**
* {@inheritDoc}
*/
@Override
public boolean contains(T value) {
for (int i = 0; i < size; i++) {
T obj = array[i];
if (obj.equals(value)) return true;
}
return false;
}
/**
* {@inheritDoc}
*/
@Override
public int size() {
return size;
}
/**
* {@inheritDoc}
*/
@Override
public boolean validate() {
int localSize = 0;
for (int i=0; i<array.length; i++) {
T t = array[i];
if (i<size) {
if (t==null) return false;
localSize++;
} else {
if (t!=null) return false;
}
}
return (localSize==size);
}
/**
* {@inheritDoc}
*/
@Override
public java.util.List<T> toList() {
return (new JavaCompatibleArrayList<T>(this));
}
/**
* {@inheritDoc}
*/
@Override
public java.util.Collection<T> toCollection() {
return (new JavaCompatibleArrayList<T>(this));
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < size; i++) {
builder.append(array[i]).append(", ");
}
return builder.toString();
}
}
public static class JavaCompatibleArrayList<T> extends java.util.AbstractList<T> implements java.util.RandomAccess {
private List.ArrayList<T> list = null;
public JavaCompatibleArrayList(List.ArrayList<T> list) {
this.list = list;
}
/**
* {@inheritDoc}
*/
@Override
public boolean add(T value) {
return list.add(value);
}
/**
* {@inheritDoc}
*/
@Override
public boolean remove(Object value) {
return list.remove((T)value);
}
/**
* {@inheritDoc}
*/
@Override
public boolean contains(Object value) {
return list.contains((T)value);
}
/**
* {@inheritDoc}
*/
@Override
public int size() {
return list.size;
}
/**
* {@inheritDoc}
*/
@Override
public void add(int index, T value) {
list.add(index, value);
}
/**
* {@inheritDoc}
*/
@Override
public T remove(int index) {
return list.remove(index);
}
/**
* {@inheritDoc}
*/
@Override
public T get(int index) {
T t = list.get(index);
if (t!=null)
return t;
throw new IndexOutOfBoundsException();
}
/**
* {@inheritDoc}
*/
@Override
public T set(int index, T value) {
return list.set(index, value);
}
}
/**
* Linked List (Singly link). A linked list is a data structure consisting
* of a group of nodes which together represent a sequence.
*
* http://en.wikipedia.org/wiki/Linked_list
*
* @author Justin Wetherell <phishman3579@gmail.com>
*/
public static class SinglyLinkedList<T> extends List<T> {
private int size = 0;
private Node<T> head = null;
private Node<T> tail = null;
/**
* {@inheritDoc}
*/
@Override
public boolean add(T value) {
return add(new Node<T>(value));
}
/**
* Add node to list.
*
* @param node
* to add to list.
*/
private boolean add(Node<T> node) {
if (head == null) {
head = node;
tail = node;
} else {
Node<T> prev = tail;
prev.next = node;
tail = node;
}
size++;
return true;
}
/**
* {@inheritDoc}
*/
@Override
public boolean remove(T value) {
// Find the node
Node<T> prev = null;
Node<T> node = head;
while (node != null && (!node.value.equals(value))) {
prev = node;
node = node.next;
}
if (node == null)
return false;
// Update the tail, if needed
if (node.equals(tail)) {
tail = prev;
if (prev != null)
prev.next = null;
}
Node<T> next = node.next;
if (prev != null && next != null) {
prev.next = next;
} else if (prev != null && next == null) {
prev.next = null;
} else if (prev == null && next != null) {
// Node is the head
head = next;
} else {
// prev==null && next==null
head = null;
}
size--;
return true;
}
/**
* {@inheritDoc}
*/
@Override
public void clear() {
head = null;
size = 0;
}
/**
* {@inheritDoc}
*/
@Override
public boolean contains(T value) {
Node<T> node = head;
while (node != null) {
if (node.value.equals(value))
return true;
node = node.next;
}
return false;
}
/**
* {@inheritDoc}
*/
@Override
public int size() {
return size;
}
/**
* {@inheritDoc}
*/
@Override
public boolean validate() {
java.util.Set<T> keys = new java.util.HashSet<T>();
Node<T> node = head;
if (node != null) {
keys.add(node.value);
Node<T> child = node.next;
while (child != null) {
if (!validate(child,keys))
return false;
child = child.next;
}
}
return (keys.size()==size);
}
private boolean validate(Node<T> node, java.util.Set<T> keys) {
if (node.value==null)
return false;
keys.add(node.value);
Node<T> child = node.next;
if (child==null) {
if (!node.equals(tail))
return false;
}
return true;
}
/**
* {@inheritDoc}
*/
@Override
public java.util.List<T> toList() {
return (new JavaCompatibleSinglyLinkedList<T>(this));
}
/**
* {@inheritDoc}
*/
@Override
public java.util.Collection<T> toCollection() {
return (new JavaCompatibleSinglyLinkedList<T>(this));
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
Node<T> node = head;
while (node != null) {
builder.append(node.value).append(", ");
node = node.next;
}
return builder.toString();
}
private static class Node<T> {
private T value = null;
private Node<T> next = null;
private Node() { }
private Node(T value) {
this.value = value;
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return "value=" + value + " next=" + ((next != null) ? next.value : "NULL");
}
}
}
/**
* Linked List (singly link). A linked list is a data structure consisting
* of a group of nodes which together represent a sequence.
*
* http://en.wikipedia.org/wiki/Linked_list
*
* @author Justin Wetherell <phishman3579@gmail.com>
*/
public static class JavaCompatibleSinglyLinkedList<T> extends java.util.AbstractSequentialList<T> {
private List.SinglyLinkedList<T> list = null;
public JavaCompatibleSinglyLinkedList(List.SinglyLinkedList<T> list) {
this.list = list;
}
/**
* {@inheritDoc}
*/
@Override
public boolean add(T value) {
return list.add(value);
}
/**
* {@inheritDoc}
*/
@Override
public boolean remove(Object value) {
return list.remove((T)value);
}
/**
* {@inheritDoc}
*/
@Override
public boolean contains(Object value) {
return list.contains((T)value);
}
/**
* {@inheritDoc}
*/
@Override
public int size() {
return list.size();
}
/**
* {@inheritDoc}
*/
@Override
public java.util.ListIterator<T> listIterator(int index) {
return (new SinglyLinkedListListIterator<T>(list));
}
private static class SinglyLinkedListListIterator<T> implements java.util.ListIterator<T> {
private int index = 0;
private SinglyLinkedList<T> list = null;
private SinglyLinkedList.Node<T> prev = null;
private SinglyLinkedList.Node<T> next = null;
private SinglyLinkedList.Node<T> last = null;
private SinglyLinkedListListIterator(SinglyLinkedList<T> list) {
this.list = list;
this.next = list.head;
this.prev = null;
this.last = null;
}
/**
* {@inheritDoc}
*/
@Override
public void add(T value) {
SinglyLinkedList.Node<T> node = new SinglyLinkedList.Node<T>(value);
if (list.head == null) {
list.head = node;
list.tail = node;
} else {
SinglyLinkedList.Node<T> p = null;
SinglyLinkedList.Node<T> n = list.head;
while (n!= null && !(n.equals(next))) {
p = node;
n = node.next;
}
if (p != null) {
p.next = node;
} else {
// replacing head
list.head = node;
}
node.next = n;
}
this.next = node;
list.size++;
}
/**
* {@inheritDoc}
*/
@Override
public void remove() {
if (last == null)
return;
SinglyLinkedList.Node<T> p = null;
SinglyLinkedList.Node<T> node = this.last;
while (node!= null && !(node.equals(last))) {
p = node;
node = node.next;
}
SinglyLinkedList.Node<T> n = last.next;
if (p != null)
p.next = n;
if (last.equals(list.head))
list.head = n;
if (last.equals(list.tail))
list.tail = p;
list.size--;
}
/**
* {@inheritDoc}
*/
@Override
public void set(T value) {
if (last != null)
last.value = value;
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasNext() {
return (next!=null);
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasPrevious() {
return (prev!=null);
}
/**
* {@inheritDoc}
*/
@Override
public int nextIndex() {
return index;
}
/**
* {@inheritDoc}
*/
@Override
public int previousIndex() {
return index-1;
}
/**
* {@inheritDoc}
*/
@Override
public T next() {
if (next == null)
throw new java.util.NoSuchElementException();
index++;
last = next;
prev = next;
next = next.next;
return last.value;
}
/**
* {@inheritDoc}
*/
@Override
public T previous() {
if (prev == null)
throw new java.util.NoSuchElementException();
index--;
last = prev;
next = prev;
SinglyLinkedList.Node<T> p = null;
SinglyLinkedList.Node<T> node = this.list.head;
while (node!= null && !(node.equals(prev))) {
p = node;
node = node.next;
}
prev = p;
return last.value;
}
}
}
/**
* Linked List (doubly link). A linked list is a data structure consisting
* of a group of nodes which together represent a sequence.
*
* http://en.wikipedia.org/wiki/Linked_list
*
* @author Justin Wetherell <phishman3579@gmail.com>
*/
public static class DoublyLinkedList<T> extends List<T> {
private int size = 0;
private Node<T> head = null;
private Node<T> tail = null;
/**
* {@inheritDoc}
*/
@Override
public boolean add(T value) {
return add(new Node<T>(value));
}
/**
* Add node to list.
*
* @param node
* to add to list.
*/
private boolean add(Node<T> node) {
if (head == null) {
head = node;
tail = node;
} else {
Node<T> prev = tail;
prev.next = node;
node.prev = prev;
tail = node;
}
size++;
return true;
}
/**
* {@inheritDoc}
*/
@Override
public boolean remove(T value) {
// Find the node
Node<T> node = head;
while (node != null && (!node.value.equals(value))) {
node = node.next;
}
if (node == null)
return false;
// Update the tail, if needed
if (node.equals(tail))
tail = node.prev;
Node<T> prev = node.prev;
Node<T> next = node.next;
if (prev != null && next != null) {
prev.next = next;
next.prev = prev;
} else if (prev != null && next == null) {
prev.next = null;
} else if (prev == null && next != null) {
// Node is the head
next.prev = null;
head = next;
} else {
// prev==null && next==null
head = null;
}
size--;
return true;
}
/**
* {@inheritDoc}
*/
@Override
public void clear() {
head = null;
size = 0;
}
/**
* {@inheritDoc}
*/
@Override
public boolean contains(T value) {
Node<T> node = head;
while (node != null) {
if (node.value.equals(value))
return true;
node = node.next;
}
return false;
}
/**
* {@inheritDoc}
*/
@Override
public int size() {
return size;
}
/**
* {@inheritDoc}
*/
@Override
public boolean validate() {
java.util.Set<T> keys = new java.util.HashSet<T>();
Node<T> node = head;
if (node!=null) {
keys.add(node.value);
if (node.prev!=null)
return false;
Node<T> child = node.next;
while (child!=null) {
if (!validate(child,keys))
return false;
child = child.next;
}
}
return (keys.size()==size);
}
private boolean validate(Node<T> node, java.util.Set<T> keys) {
if (node.value==null)
return false;
keys.add(node.value);
Node<T> child = node.next;
if (child!=null) {
if (!child.prev.equals(node))
return false;
} else {
if (!node.equals(tail))
return false;
}
return true;
}
/**
* {@inheritDoc}
*/
@Override
public java.util.List<T> toList() {
return (new JavaCompatibleDoublyLinkedList<T>(this));
}
/**
* {@inheritDoc}
*/
@Override
public java.util.Collection<T> toCollection() {
return (new JavaCompatibleDoublyLinkedList<T>(this));
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
Node<T> node = head;
while (node != null) {
builder.append(node.value).append(", ");
node = node.next;
}
return builder.toString();
}
private static class Node<T> {
private T value = null;
private Node<T> prev = null;
private Node<T> next = null;
private Node() { }
private Node(T value) {
this.value = value;
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return "value=" + value + " previous=" + ((prev != null) ? prev.value : "NULL")
+ " next=" + ((next != null) ? next.value : "NULL");
}
}
}
public static class JavaCompatibleDoublyLinkedList<T> extends java.util.AbstractSequentialList<T> {
private List.DoublyLinkedList<T> list = null;
public JavaCompatibleDoublyLinkedList(List.DoublyLinkedList<T> list) {
this.list = list;
}
/**
* {@inheritDoc}
*/
@Override
public boolean add(T value) {
return list.add(value);
}
/**
* {@inheritDoc}
*/
@Override
public boolean remove(Object value) {
return list.remove((T)value);
}
/**
* {@inheritDoc}
*/
@Override
public boolean contains(Object value) {
return list.contains((T)value);
}
/**
* {@inheritDoc}
*/
@Override
public int size() {
return list.size();
}
/**
* {@inheritDoc}
*/
@Override
public java.util.ListIterator<T> listIterator(int index) {
return (new DoublyLinkedListListIterator<T>(list));
}
private static class DoublyLinkedListListIterator<T> implements java.util.ListIterator<T> {
private int index = 0;
private DoublyLinkedList<T> list = null;
private DoublyLinkedList.Node<T> prev = null;
private DoublyLinkedList.Node<T> next = null;
private DoublyLinkedList.Node<T> last = null;
private DoublyLinkedListListIterator(DoublyLinkedList<T> list) {
this.list = list;
this.next = list.head;
this.prev = null;
this.last = null;
}
/**
* {@inheritDoc}
*/
@Override
public void add(T value) {
DoublyLinkedList.Node<T> node = new DoublyLinkedList.Node<T>(value);
DoublyLinkedList.Node<T> n = this.next;
if (this.prev != null)
this.prev.next = node;
node.prev = this.prev;
node.next = n;
if (n != null)
n.prev = node;
this.next = node;
if (this.prev == null)
list.head = node; // new root
list.size++;
}
/**
* {@inheritDoc}
*/
@Override
public void remove() {
if (last == null)
return;
DoublyLinkedList.Node<T> p = last.prev;
DoublyLinkedList.Node<T> n = last.next;
if (p != null)
p.next = n;
if (n != null)
n.prev = p;
if (last.equals(list.head))
list.head = n;
if (last.equals(list.tail))
list.tail = p;
list.size--;
}
/**
* {@inheritDoc}
*/
@Override
public void set(T value) {
if (last != null)
last.value = value;
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasNext() {
return (next!=null);
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasPrevious() {
return (prev!=null);
}
/**
* {@inheritDoc}
*/
@Override
public int nextIndex() {
return index;
}
/**
* {@inheritDoc}
*/
@Override
public int previousIndex() {
return index-1;
}
/**
* {@inheritDoc}
*/
@Override
public T next() {
if (next == null)
throw new java.util.NoSuchElementException();
index++;
last = next;
prev = next;
next = next.next;
return last.value;
}
/**
* {@inheritDoc}
*/
@Override
public T previous() {
if (prev == null)
throw new java.util.NoSuchElementException();
index--;
last = prev;
next = prev;
prev = next.prev;
return last.value;
}
}
}
}