All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.amygdalum.util.graph.GraphNode Maven / Gradle / Ivy

The newest version!
package net.amygdalum.util.graph;

import java.util.HashMap;
import java.util.ListIterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;

public class GraphNode> {

	private T key;
	private Map, Object> data;
	private GraphNode[] predecessors;
	private GraphNode[] successors;

	@SuppressWarnings("unchecked")
	public GraphNode(T key) {
		this.key = key;
		this.data = new HashMap<>();
		this.predecessors = new GraphNode[0];
		this.successors = new GraphNode[0];
	}

	public T getKey() {
		return key;
	}

	public  S getData(DataDescriptor desc) {
		return desc.from(data);
	}

	public  void setData(DataDescriptor desc, S data) {
		desc.to(this.data, data);
	}

	public void addPredecessor(GraphNode pre) {
		int index = binarySearchFor(predecessors, pre.getKey());
		if (index < predecessors.length && predecessors[index] == pre) {
			return;
		}

		@SuppressWarnings("unchecked")
		GraphNode[] newpredecessors = new GraphNode[predecessors.length + 1];

		System.arraycopy(predecessors, 0, newpredecessors, 0, index);
		newpredecessors[index] = pre;
		System.arraycopy(predecessors, index, newpredecessors, index + 1, predecessors.length - index);
		predecessors = newpredecessors;
	}

	public GraphNode[] getPredecessors() {
		return predecessors;
	}

	public ListIterator> predecessorsFor(T key) {
		return new PredecessorIterator<>(this, key);
	}

	public void addSuccessor(GraphNode suc) {
		int index = binarySearchFor(successors, suc.getKey());
		if (index < successors.length && successors[index] == suc) {
			return;
		}

		@SuppressWarnings("unchecked")
		GraphNode[] newsuccessors = new GraphNode[successors.length + 1];

		System.arraycopy(successors, 0, newsuccessors, 0, index);
		newsuccessors[index] = suc;
		System.arraycopy(successors, index, newsuccessors, index + 1, successors.length - index);
		successors = newsuccessors;
	}

	public GraphNode[] getSuccessors() {
		return successors;
	}

	public ListIterator> successorsFor(T key) {
		return new SuccessorIterator<>(this, key);
	}

	private static > int binarySearchFor(GraphNode[] array, S key) {
		if (array.length == 0) {
			return 0;
		} else if (key.compareTo(array[0].key) <= 0) {
			return 0;
		} else if (key.compareTo(array[array.length - 1].key) > 0) {
			return array.length;
		}
		int low = 0;
		int high = array.length - 1;
		while (low+1 < high) {
			int pivot = (low + high) / 2;
			S pivotKey = array[pivot].key;
			int comp = key.compareTo(pivotKey);
			if (comp <= 0) {
				high = pivot;
			} else {
				low = pivot;
			}
		}
		if (array[low].key.equals(key)) {
			return low;
		} else if(array[high].key.equals(key)) {
			return high;
		} else {
			return high;
		}
	}

	@Override
	public String toString() {
		return Objects.toString(key);
	}

	private abstract static class ArrayIterator> implements ListIterator> {

		protected GraphNode node;
		protected GraphNode[] array;
		protected T key;
		protected int index;

		public ArrayIterator(GraphNode node, GraphNode[] array, T key, int index) {
			this.node = node;
			this.array = array;
			this.key = key;
			this.index = index;
		}
		
		@Override
		public boolean hasNext() {
			if (index >= array.length || !key.equals(array[index].key)) {
				return false;
			}
			return true;
		}

		@Override
		public GraphNode next() {
			if (index >= array.length || !key.equals(array[index].key)) {
				throw new NoSuchElementException();
			}
			GraphNode result = array[index];
			index++;
			return result;
		}

		@Override
		public boolean hasPrevious() {
			if (index <= 0 || !key.equals(array[index-1].key)) {
				return false;
			}
			return true;
		}

		@Override
		public GraphNode previous() {
			if (index <= 0 || !key.equals(array[index-1].key)) {
				throw new NoSuchElementException();
			}
			GraphNode result = array[index-1];
			index--;
			return result;
		}

		@Override
		public int nextIndex() {
			return index;
		}

		@Override
		public int previousIndex() {
			return index-1;
		}
	}
	
	private static class PredecessorIterator> extends ArrayIterator {

		
		public PredecessorIterator(GraphNode node, T key) {
			super(node, node.predecessors, key, binarySearchFor(node.predecessors, key));
		}

		@Override
		public void remove() {
			@SuppressWarnings("unchecked")
			GraphNode[] newarray = new GraphNode[array.length - 1];

			System.arraycopy(array, 0, newarray, 0, index);
			System.arraycopy(array, index + 1, newarray, index, array.length - index - 1);
			node.predecessors = newarray;
			array = node.predecessors;
		}

		@Override
		public void set(GraphNode e) {
			node.predecessors[index] = e;
			array = node.predecessors;
		}

		@Override
		public void add(GraphNode e) {
			@SuppressWarnings("unchecked")
			GraphNode[] newarray = new GraphNode[array.length + 1];

			System.arraycopy(array, 0, newarray, 0, index);
			newarray[index] = e;
			System.arraycopy(array, index, newarray, index + 1, array.length - index);
			node.predecessors = newarray;
			array = node.predecessors;
		}

	}

	private static class SuccessorIterator> extends ArrayIterator {
		
		public SuccessorIterator(GraphNode node, T key) {
			super(node, node.successors, key, binarySearchFor(node.successors, key));
		}

		@Override
		public void remove() {
			@SuppressWarnings("unchecked")
			GraphNode[] newarray = new GraphNode[array.length - 1];

			System.arraycopy(array, 0, newarray, 0, index);
			System.arraycopy(array, index + 1, newarray, index, array.length - index - 1);
			node.successors = newarray;
			array = node.successors;
		}

		@Override
		public void set(GraphNode e) {
			node.successors[index] = e;
			array = node.successors;
		}

		@Override
		public void add(GraphNode e) {
			@SuppressWarnings("unchecked")
			GraphNode[] newarray = new GraphNode[array.length + 1];

			System.arraycopy(array, 0, newarray, 0, index);
			newarray[index] = e;
			System.arraycopy(array, index, newarray, index + 1, array.length - index);
			node.successors = newarray;
			array = node.successors;
		}

	}
	
}