import java.util.*; class MergeSorter { /** Sort data (according to its elements' compareTo). * @param data The list to sort. Not modified. * @return A new, sorted list containing all the elements of data. * The result shares no storage with `data` (except for the * contents themselves, of course). */ static > List mergeSort( List data ) { int n = data.size(); if (n <= 1) { return data; } else { int mid = n/2; List firstHalf = new ArrayList( mid-0 ); List secondHalf = new ArrayList( n-mid ); for (int i = 0; i < mid; ++i) { firstHalf.add( data.get(i) ); } for (int i = mid; i < n; ++i) { secondHalf.add( data.get(i) ); } return merge( mergeSort(firstHalf), mergeSort(secondHalf) ); } } /** Given two sorted lists, merge them new one. * @param dataA a sorted list of data. `dataA` is not modified. * @param dataB a sorted list of data. `dataB` is not modified. * @return a sorted list containing all the elements of dataA and dataB. * The result shares no storage with the inputs * (except for the contents themselves, of course). */ static > List merge( List dataA, List dataB ) { int a=0; // Index into dataA: how far we've already merged. int b=0; List merged = new ArrayList( dataA.size() + dataB.size() ); // A new list to hold the merged result. while (a> List merge( List listOne, List listTwo ) { List dataA = new LinkedList(listOne); // Make *copies* of our inputs, so that we can List dataB = new LinkedList(listTwo); // remove items w/o disturbing originals. List merged = new LinkedList(); // A new list with the merged result. while ((!dataA.isEmpty() && !dataB.isEmpty())) { List holdsSmaller = (dataA.get(0).compareTo(dataB.get(0)) < 0) ? dataA : dataB; merged.add(holdsSmaller.get(0)); holdsSmaller.remove(0); } merged.addAll( dataA ); // If dataB was emptied first, dataA still has some (large) items. merged.addAll( dataB ); return merged; } */ static void test() { assertResults( new ArrayList() ); assertResults(3); assertResults( new ArrayList( Arrays.asList(3,4) ) ); assertResults( new ArrayList( Arrays.asList(4,3) ) ); assertResults( new ArrayList( Arrays.asList(3,4,5) ) ); assertResults( new ArrayList( Arrays.asList(3,5,4) ) ); assertResults( new ArrayList( Arrays.asList(4,3,5) ) ); assertResults( new ArrayList( Arrays.asList(4,5,3) ) ); assertResults( new ArrayList( Arrays.asList(5,3,4) ) ); assertResults( new ArrayList( Arrays.asList(5,4,3) ) ); assertResults( new ArrayList( Arrays.asList(2,3,3,4) ) ); assertResults( new ArrayList( Arrays.asList(2,4,3,3) ) ); assertResults( new ArrayList( Arrays.asList(3,3,2,4) ) ); assertResults( new ArrayList( Arrays.asList(3,4,2,3) ) ); assertResults( new ArrayList( Arrays.asList(2,3,3,4,4) ) ); assertResults( new ArrayList( Arrays.asList(4,3,4,2,3) ) ); assertResults( new ArrayList( Arrays.asList(4,3,4,2,3) ) ); assertResults( new ArrayList( Arrays.asList(4,3,4,2,3,7,19,-3,4,-3,19,7,4,-3) ) ); assertResults( new ArrayList() ); assertResults( "hi" ); assertResults( "hi", "bye" ); assertResults( "bye", "hi" ); assertResults( "hi", "hit" ); assertResults( "hit", "hi" ); assertResults( "hit", "hi", "hippo", "hittite", "hinnie", "hill", "hit", "hi", "hi", "hi", "hit", "hips", "hiccough" ); } static > void assertResults( T... dataArray ) { assertResults( Arrays.asList(dataArray) ); } static > void assertResults( List data ) { List original = new ArrayList( data ); List sordid = MergeSorter.mergeSort(data); Collections.sort(data); // destructive sort. System.out.print( "Sorting " + original.toString() + "..."); if (! sordid.equals(data)) { System.err.println( "Uh-oh!:\n" + "expected " + data.toString() + "\n" + "but got " + MergeSorter.mergeSort(data).toString() ); } System.out.println( "done." ); } }