You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

PartialOrder.java 5.9KB

21 years ago
21 years ago
21 years ago
14 years ago
21 years ago
14 years ago
21 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
21 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /* *******************************************************************
  2. * Copyright (c) 1999-2001 Xerox Corporation,
  3. * 2002 Palo Alto Research Center, Incorporated (PARC).
  4. * All rights reserved.
  5. * This program and the accompanying materials are made available
  6. * under the terms of the Eclipse Public License v1.0
  7. * which accompanies this distribution and is available at
  8. * http://www.eclipse.org/legal/epl-v10.html
  9. *
  10. * Contributors:
  11. * Xerox/PARC initial implementation
  12. * ******************************************************************/
  13. package org.aspectj.util;
  14. import java.util.ArrayList;
  15. import java.util.Iterator;
  16. import java.util.LinkedList;
  17. import java.util.List;
  18. /**
  19. * This class implements a partial order
  20. *
  21. * It includes routines for doing a topo-sort
  22. */
  23. public class PartialOrder {
  24. /**
  25. * All classes that want to be part of a partial order must implement PartialOrder.PartialComparable.
  26. */
  27. public static interface PartialComparable {
  28. /**
  29. * @returns <ul>
  30. * <li>+1 if this is greater than other</li>
  31. * <li>-1 if this is less than other</li>
  32. * <li>0 if this is not comparable to other</li>
  33. * </ul>
  34. *
  35. * <b> Note: returning 0 from this method doesn't mean the same thing as returning 0 from
  36. * java.util.Comparable.compareTo()</b>
  37. */
  38. public int compareTo(Object other);
  39. /**
  40. * This method can provide a deterministic ordering for elements that are strictly not comparable. If you have no need for
  41. * this, this method can just return 0 whenever called.
  42. */
  43. public int fallbackCompareTo(Object other);
  44. }
  45. private static class SortObject<T extends PartialComparable> {
  46. T object;
  47. List<SortObject<T>> smallerObjects = new LinkedList<SortObject<T>>();
  48. List<SortObject<T>> biggerObjects = new LinkedList<SortObject<T>>();
  49. public SortObject(T o) {
  50. object = o;
  51. }
  52. boolean hasNoSmallerObjects() {
  53. return smallerObjects.size() == 0;
  54. }
  55. boolean removeSmallerObject(SortObject<T> o) {
  56. smallerObjects.remove(o);
  57. return hasNoSmallerObjects();
  58. }
  59. void addDirectedLinks(SortObject<T> other) {
  60. int cmp = object.compareTo(other.object);
  61. if (cmp == 0) {
  62. return;
  63. }
  64. if (cmp > 0) {
  65. this.smallerObjects.add(other);
  66. other.biggerObjects.add(this);
  67. } else {
  68. this.biggerObjects.add(other);
  69. other.smallerObjects.add(this);
  70. }
  71. }
  72. public String toString() {
  73. return object.toString(); // +smallerObjects+biggerObjects;
  74. }
  75. }
  76. private static <T extends PartialComparable> void addNewPartialComparable(List<SortObject<T>> graph, T o) {
  77. SortObject<T> so = new SortObject<T>(o);
  78. for (Iterator<SortObject<T>> i = graph.iterator(); i.hasNext();) {
  79. SortObject<T> other = i.next();
  80. so.addDirectedLinks(other);
  81. }
  82. graph.add(so);
  83. }
  84. private static <T extends PartialComparable> void removeFromGraph(List<SortObject<T>> graph, SortObject<T> o) {
  85. for (Iterator<SortObject<T>> i = graph.iterator(); i.hasNext();) {
  86. SortObject<T> other = i.next();
  87. if (o == other) {
  88. i.remove();
  89. }
  90. // ??? could use this to build up a new queue of objects with no
  91. // ??? smaller ones
  92. other.removeSmallerObject(o);
  93. }
  94. }
  95. /**
  96. * @param objects must all implement PartialComparable
  97. *
  98. * @returns the same members as objects, but sorted according to their partial order. returns null if the objects are cyclical
  99. *
  100. */
  101. public static <T extends PartialComparable> List<T> sort(List<T> objects) {
  102. // lists of size 0 or 1 don't need any sorting
  103. if (objects.size() < 2) {
  104. return objects;
  105. }
  106. // ??? we might want to optimize a few other cases of small size
  107. // ??? I don't like creating this data structure, but it does give good
  108. // ??? separation of concerns.
  109. List<SortObject<T>> sortList = new LinkedList<SortObject<T>>();
  110. for (Iterator<T> i = objects.iterator(); i.hasNext();) {
  111. addNewPartialComparable(sortList, i.next());
  112. }
  113. // System.out.println(sortList);
  114. // now we have built our directed graph
  115. // use a simple sort algorithm from here
  116. // can increase efficiency later
  117. // List ret = new ArrayList(objects.size());
  118. final int N = objects.size();
  119. for (int index = 0; index < N; index++) {
  120. // System.out.println(sortList);
  121. // System.out.println("-->" + ret);
  122. SortObject<T> leastWithNoSmallers = null;
  123. for (SortObject<T> so: sortList) {
  124. if (so.hasNoSmallerObjects()) {
  125. if (leastWithNoSmallers == null || so.object.fallbackCompareTo(leastWithNoSmallers.object) < 0) {
  126. leastWithNoSmallers = so;
  127. }
  128. }
  129. }
  130. if (leastWithNoSmallers == null) {
  131. return null;
  132. }
  133. removeFromGraph(sortList, leastWithNoSmallers);
  134. objects.set(index, leastWithNoSmallers.object);
  135. }
  136. return objects;
  137. }
  138. /***********************************************************************************
  139. * /* a minimal testing harness
  140. ***********************************************************************************/
  141. static class Token implements PartialComparable {
  142. private String s;
  143. Token(String s) {
  144. this.s = s;
  145. }
  146. public int compareTo(Object other) {
  147. Token t = (Token) other;
  148. int cmp = s.charAt(0) - t.s.charAt(0);
  149. if (cmp == 1) {
  150. return 1;
  151. }
  152. if (cmp == -1) {
  153. return -1;
  154. }
  155. return 0;
  156. }
  157. public int fallbackCompareTo(Object other) {
  158. return -s.compareTo(((Token) other).s);
  159. }
  160. public String toString() {
  161. return s;
  162. }
  163. }
  164. public static void main(String[] args) {
  165. List<Token> l = new ArrayList<Token>();
  166. l.add(new Token("a1"));
  167. l.add(new Token("c2"));
  168. l.add(new Token("b3"));
  169. l.add(new Token("f4"));
  170. l.add(new Token("e5"));
  171. l.add(new Token("d6"));
  172. l.add(new Token("c7"));
  173. l.add(new Token("b8"));
  174. l.add(new Token("z"));
  175. l.add(new Token("x"));
  176. l.add(new Token("f9"));
  177. l.add(new Token("e10"));
  178. l.add(new Token("a11"));
  179. l.add(new Token("d12"));
  180. l.add(new Token("b13"));
  181. l.add(new Token("c14"));
  182. System.out.println(l);
  183. sort(l);
  184. System.out.println(l);
  185. }
  186. }