001 /* 002 * LAPIS lightweight structured text processing system 003 * 004 * Copyright (C) 1998-2002 Carnegie Mellon University, 005 * Copyright (C) 2003 Massachusetts Institute of Technology. 006 * All rights reserved. 007 * 008 * This library is free software; you can redistribute it 009 * and/or modify it under the terms of the GNU General 010 * Public License as published by the Free Software 011 * Foundation, version 2. 012 * 013 * LAPIS homepage: http://graphics.lcs.mit.edu/lapis/ 014 */ 015 016 package lapisx.sort; 017 018 import java.util.Vector; 019 020 public abstract class MergeSort { 021 022 public static void sort (Sortable a) { 023 Vector buffer = new Vector (); 024 buffer.setSize (a.size ()); 025 sort (a, 0, a.size()-1, buffer); 026 } 027 028 public static void sort (Sortable a, int p, int r, Vector buffer) { 029 if (p < r) { 030 int q = (p + r)/2; 031 sort (a, p, q, buffer); 032 sort (a, q+1, r, buffer); 033 merge (a, p, q, r, buffer); 034 } 035 } 036 037 private static void merge (Sortable a, int p, int q, int r, Vector buffer) { 038 int k = 0; 039 int i = p; 040 int j = q + 1; 041 Object objI = a.get (i); 042 Object objJ = a.get (j); 043 while (true) { 044 if (a.compare (objI, objJ) <= 0) { 045 buffer.setElementAt (objI, k); 046 ++k; 047 ++i; 048 if (i > q) 049 break; 050 objI = a.get (i); 051 } else { 052 buffer.setElementAt (objJ, k); 053 ++k; 054 ++j; 055 if (j > r) 056 break; 057 objJ = a.get (j); 058 } 059 } 060 061 while (i <= q) { 062 buffer.setElementAt (a.get (i), k); 063 ++k; 064 ++i; 065 } 066 067 while (j <= r) { 068 buffer.setElementAt (a.get (j), k); 069 ++k; 070 ++j; 071 } 072 073 for (i = 0; i < k; ++i) 074 a.set (p + i, buffer.elementAt (i)); 075 } 076 077 078 public static SortableList sort (SortableList l) { 079 return sort (l, count (l)); 080 } 081 082 public static SortableList sort (SortableList l, int n) { 083 if (n < 2) 084 return l; 085 086 int half = n/2; 087 SortableList l1 = l; 088 SortableList l1End = traverse (l, half-1); 089 SortableList l2 = l1End.next (); 090 l1End.setNext (null); 091 092 // l1 is now a list of half elements, 093 // l2 is now a list of n-half elements. 094 // Sort l1 and l2 separately and merge them. 095 l1 = sort (l1, half); 096 l2 = sort (l2, n-half); 097 098 return merge (l1, l2); 099 } 100 101 private static SortableList merge (SortableList l1, SortableList l2) { 102 SortableList header = new DummySortableList (); 103 SortableList l = header; 104 105 while (l1 != null && l2 != null) { 106 if(l1.compareTo (l2) <= 0) { 107 l.setNext (l1); 108 l = l1; 109 l1 = l1.next (); 110 } 111 else { 112 l.setNext (l2); 113 l = l2; 114 l2 = l2.next (); 115 } 116 } 117 118 if (l1 != null) 119 l.setNext (l1); 120 else if (l2 != null) 121 l.setNext (l2); 122 else 123 l.setNext (null); 124 125 return header.next (); 126 } 127 128 static class DummySortableList implements SortableList { 129 SortableList nextPtr; 130 public Object get () { return null; } 131 public SortableList next () { return nextPtr; } 132 public void setNext (SortableList l) { nextPtr = l; } 133 public int compareTo (SortableList l) { return 0; } 134 } 135 136 private static SortableList traverse (SortableList l, int n) { 137 while (n > 0) { 138 l = l.next (); 139 --n; 140 } 141 return l; 142 } 143 144 private static int count (SortableList l) { 145 int n = 0; 146 for (SortableList p = l; p != null; p = p.next ()) 147 ++n; 148 return n; 149 } 150 151 public static void test (String[] args) { 152 StringSortableList list = StringSortableList.make (args); 153 list = (StringSortableList)MergeSort.sort (list); 154 System.out.print ("list sort: "); 155 if (list != null) 156 list.dump (); 157 System.out.println (); 158 159 Vector v = new Vector (); 160 for (int i = 0; i < args.length; ++i) 161 v.addElement (args[i]); 162 MergeSort.sort (new SortableVector (v)); 163 System.out.print ("array sort: "); 164 for (int i = 0; i < v.size (); ++i) 165 System.out.print (v.elementAt (i) + " "); 166 System.out.println (); 167 168 169 } 170 171 public static void main (String[] args) { 172 if (args.length > 0) 173 test (args); 174 else { 175 test (new String[] {"b", "d", "a", "c"}); 176 test (new String[] {"a", "b", "c", "d"}); 177 test (new String[] {"d", "c", "b", "a"}); 178 179 test (new String[] {"a", "b", "c"}); 180 test (new String[] {"c", "b", "a"}); 181 182 test (new String[] {"a", "b"}); 183 test (new String[] {"b", "a"}); 184 185 test (new String[] {"a"}); 186 187 test (new String[] {}); 188 189 String[] random = new String[100]; 190 for (int i = 0; i < random.length; ++i) 191 random[i] = String.valueOf ((char)('a' + 26 * Math.random ())); 192 test (random); 193 } 194 } 195 }