/* * Kodkod -- Copyright (c) 2005-present, Emina Torlak * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package kodkod.util.collections; import java.util.EmptyStackException; import java.util.Iterator; import java.util.NoSuchElementException; /** * A Stack implementation based on a singly linked list. * @author Emina Torlak */ public final class LinkedStack<T> extends Stack<T> { private StackEntry<T> head; private int size; /** * Constructs an empty stack. * @ensures no this.elems' */ public LinkedStack() { head = null; size = 0; } /** * @see kodkod.util.collections.Stack#size() */ public int size() { return size; } /** * Pushes an item onto the top of this stack and returns it. * @ensures this.size' = this.size + 1 && this.elems'[0] = item && * all i: [0..this.size) | this.elems'[i+1] = this.elems[i] * @return item */ public T push(T item) { head = new StackEntry<T>(item, head); size++; return item; } /** * Removes the object at the top of this stack and returns that object as the value of this function. * @ensures this.size' = this.size - 1 && * all i: [1..this.size) | this.elems'[i-1] = this.elems[i] * @return this.elems[0] * @throws EmptyStackException no this.elems */ public T pop() { if (head==null) throw new EmptyStackException(); final T pop = head.data; head = head.next; size--; return pop; } /** * Looks at the object at the top of this stack without removing it from the stack. * @return this.elems[0] * @throws EmptyStackException no this.elems */ public T peek() { if (head==null) throw new EmptyStackException(); return head.data; } /** * Returns the 1-based position where an object is on this stack. * If the object o occurs as an item in this stack, this method * returns the distance from the top of the stack of the occurrence * nearest the top of the stack; the topmost item on the stack is * considered to be at distance 1. The equals method is used to * compare o to the items in this stack. * @return o in this.elems[int] => min(this.elems.o) + 1, -1 */ public int search(Object o) { StackEntry<T> e = head; int position = 1; while(e != null) { if (equal(o, e.data)) return position; e = e.next; position++; } return -1; } /** * Returns true if the stack is empty; otherwise returns false. * @return no this.elems */ public boolean empty() { return head == null; } /** * Iterates over the items in this LinkedStack, starting * at the top of the stack and working its way down. * @return iterator over the elements in this stack. */ public Iterator<T> iterator() { return new Iterator<T>() { private StackEntry<T> cursor = head, prev = null, pprev = null; public boolean hasNext() { return cursor != null; } public T next() { if (cursor==null) throw new NoSuchElementException(); pprev = prev; prev = cursor; cursor = cursor.next; return prev.data; } public void remove() { if (prev==pprev) { throw new UnsupportedOperationException(); } else if (prev==head) { head = cursor; } else { pprev.next = cursor; prev.next = null; } prev = pprev; size--; } }; } /** * Represents a stack entry. * @specfield data: T * @specfield next: StackEntry<T> */ private static final class StackEntry<T> { T data; StackEntry<T> next; StackEntry(T data, StackEntry<T> next) { this.data = data; this.next = next; } } }