/* * Copyright 1996-2002 by Andruid Kerne. All rights reserved. * CONFIDENTIAL. Use is subject to license terms. */ package ecologylab.collections; //import java.awt.Toolkit; import java.util.Iterator; import ecologylab.generic.Debug; /** * Doubly linked list of GUI components. Maintains family tree. */ public class DLL<T> extends Debug implements Iterable<T> { private DLL<T> prevSib; private DLL<T> nextSib; private T object; public DLL(T objectArg) { object = objectArg; } /** * Add sibs after ourself. */ public synchronized void addAfter(DLL<T> sibs) { sibs.setNext(nextSib); addToEnd(sibs); } /** * Insert sibs before ourself. */ public synchronized void insertBefore(DLL<T> sibs) { sibs.setPrev(prevSib); if (prevSib != null) prevSib.setNext(sibs); sibs.setNext(this); prevSib = sibs; } /** * Add sibs to the end of this. * * @param sibs DLL for object added to the end of this. */ public void addToEnd(DLL<T> sibs) { if (sibs == this) { debug("ERROR!!!! adding to end of self!!!!"); //Toolkit.getDefaultToolkit().beep(); Thread.dumpStack(); } nextSib = sibs; // ??? should this be setNext(sibs) -- sync // setNext(sibs); sibs.setPrev(this); } /** * Prepend sibs to the start of this. * * @param sibs DLL for object added before this. */ public void addAtBeginning(DLL<T> sibs) { if (sibs == this) { debug("ERROR!!!! adding to end of self!!!!"); // /Toolkit.getDefaultToolkit().beep(); Thread.dumpStack(); } prevSib = sibs; // ??? should this be setNext(sibs) -- sync // setNext(sibs); sibs.setNext(this); } /** * Remove I and I from the dll of sibs. */ public synchronized void remove() { if (nextSib != null) nextSib.setPrev(prevSib); if (prevSib != null) prevSib.setNext(nextSib); prevSib = null; nextSib = null; //FIXME -- uncomment this out! // object = null; // encourage gc ?? -- why is this commented out??? andruid 2/10/08 } /** * Remove the relations of this node, while it is being manipulated in * the midst of mergeSort(). */ public void clear() { prevSib = null; nextSib = null; // remove(); object = null; } /** * Remove the relations of this node, while it is being deleted. */ public void clearStronger() { remove(); object = null; } /** * Remove the relations of this node, while it is being rebuilt, and * its associations are meaningless. */ public void clearRelations() { prevSib = null; nextSib = null; } /** * Not usually for public consumption. Only available for special sorts. * With a getKey interface, the sort could be brought here, which will * be better oo design. */ public synchronized void setNext(DLL<T> next) { nextSib = next; } public synchronized void setPrev(DLL<T> prev) { prevSib = prev; } public T getThis() { return object; } public synchronized T getNext() { return (nextSib == null) ? null : nextSib.object; } public synchronized T getPrev() { return (prevSib == null) ? null : prevSib.object; } public DLL<T> prev() { return prevSib; } public DLL<T> next() { return nextSib; } public DLL<T> mergeSortDescending(MergeD<T> mergeD, DLL<T> zSibs) { DLL<T> c = this; int n = 1; DLL<T> head = new DLL<T>(null); head.setNext(c); DLL<T> a; do { DLL<T> todo = head.next(); c = head; int toMove = n - 1; // System.out.println(""); // visualize.CollageElement.printPieces(c.next(), zSibs); // System.out.println("start inner loop moving " + toMove); do { // merge lists of size n DLL<T> t = todo; a = t; for (int i=1; i<=toMove; i++) t = t.next(); DLL<T> b = t.next(); t.setNext(zSibs); t = b; for (int i=1; i<=toMove; i++) t = t.next(); todo = t.next(); t.setNext(zSibs); // System.out.println("mergeDescending(a: "); // visualize.CollageElement.printPieces(a, zSibs); // System.out.println("mergeDescending(b: "); // visualize.CollageElement.printPieces(b, zSibs); c.setNext(mergeD.mergeDescending(a,b)); // System.out.println("returns: "); // visualize.CollageElement.printPieces(c.next(), zSibs); int twoN = n + n; for (int i=1; i<=twoN; i++) c = c.next(); } while (todo != zSibs); n += n; } while (a != head.next()); DLL<T> something = head; DLL<T> prev = something; while (something != null) { something = something.next(); if (something == prev) prev.setNext(null); prev = something; } return head.next(); } /** * @param object the object to set */ public void setObject(T object) { this.object = object; } /** * Create an {@code Iterator} object for this {@code DLL}. * * @return an {@code Iterator} object for iterating over all elements in this {@code DLL}. */ @Override public Iterator<T> iterator() { return new DLLIterator(); } /** * Iterator class for building an iterator object out of the DLL. Uses current * DLL structure for iteration, starting at the DLL object that instantiates it. * */ private class DLLIterator implements Iterator<T> { DLL<T> currentNode = DLL.this; DLL<T> firstObject = DLL.this; boolean stop = false; @Override public boolean hasNext() { return !stop && (currentNode != null && currentNode.object != null); } @Override public T next() { T currentObject = currentNode.object; currentNode = currentNode.next(); if (currentNode == firstObject) stop = true; return currentObject; } @Override public void remove() { // optional method that is not needed in our case. } } }