/******************************************************************************* * Copyright 2011 See AUTHORS file. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package com.badlogic.gdx.utils; /** A sorted double linked list which uses ints for indexing * * @param <E> */ public class SortedIntList<E> implements Iterable<SortedIntList.Node<E>> { private NodePool<E> nodePool = new NodePool<E>(); // avoid allocating nodes private Iterator iterator; int size = 0; Node<E> first; /** Creates an ascending list */ public SortedIntList () { } /** Inserts an element into the list at the given index * * @param index Index of the element * @param value Element to insert * @return Element replaced by newly inserted element, null if nothing was replaced */ public E insert (int index, E value) { if (first != null) { Node<E> c = first; // iterate to the right until we can't move any further because the next number is bigger than index while (c.n != null && c.n.index <= index) { c = c.n; } // add one to the right if (index > c.index) { c.n = nodePool.obtain(c, c.n, value, index); if (c.n.n != null) { c.n.n.p = c.n; } size++; } // the new element is smaller than every other element else if (index < c.index) { Node<E> newFirst = nodePool.obtain(null, first, value, index); first.p = newFirst; first = newFirst; size++; } // that element already exists so swap the value else { c.value = value; } } else { first = nodePool.obtain(null, null, value, index); size++; } return null; } /** Retrieves an element at a given index * * @param index Index of the element to retrieve * @return Matching element, null otherwise */ public E get (int index) { E match = null; if (first != null) { Node<E> c = first; while (c.n != null && c.index < index) { c = c.n; } if (c.index == index) { match = c.value; } } return match; } /** Clears list */ public void clear () { for (; first != null; first = first.n) { nodePool.free(first); } size = 0; } /** @return size of list equal to elements contained in it */ public int size () { return size; } /** Returns an iterator to traverse the list.<br/> * Only one iterator can be active per list at any given time. * * @return Iterator to traverse list */ public java.util.Iterator<Node<E>> iterator () { if (iterator == null) { iterator = new Iterator(); } return iterator.reset(); } class Iterator implements java.util.Iterator<Node<E>> { private Node<E> position; private Node<E> previousPosition; @Override public boolean hasNext () { return position != null; } @Override public Node<E> next () { previousPosition = position; position = position.n; return previousPosition; } @Override public void remove () { // the contract specifies to remove the last returned element, if nothing was returned yet assumably do nothing if (previousPosition != null) { // if we are at the second element set it as the first element if (previousPosition == first) { first = position; } // else remove last returned element by changing the chain else { previousPosition.p.n = position; if (position != null) { position.p = previousPosition.p; } } size--; } } public Iterator reset () { position = first; previousPosition = null; return this; } } public static class Node<E> { /** Node previous to this */ protected Node<E> p; /** Node next to this */ protected Node<E> n; /** Value held */ public E value; /** Index value in list */ public int index; } static class NodePool<E> extends Pool<Node<E>> { @Override protected Node<E> newObject () { return new Node<E>(); } public Node<E> obtain (Node<E> p, Node<E> n, E value, int index) { Node<E> newNode = super.obtain(); newNode.p = p; newNode.n = n; newNode.value = value; newNode.index = index; return newNode; } } }