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.Random;
019    
020    public abstract class Quicksort {
021        private static Random random = new Random ();
022    
023    
024        //
025        // sorting collections of objects
026        //
027    
028        public static void sort (Sortable a) {
029            sort (a, 0, a.size()-1);
030        }
031    
032        public static void sort (Sortable a, int p, int r) {
033            if (p < r) {
034                int q = partition (a, p, r);
035                sort (a, p, q);
036                sort (a, q+1, r);
037            }
038        }
039    
040        private static int partition (Sortable a, int p, int r) {
041            Object x = a.get (p + Math.abs (random.nextInt () % (r-p+1)));
042            int i = p-1;
043            int j = r+1;
044            while (true) {
045                do j = j-1;
046                while (a.compare (a.get (j), x) > 0);
047                do i = i+1;
048                while (a.compare (a.get (i), x) < 0);
049                if (i < j)
050                    a.swap (i, j);
051                else return j;
052            }
053        }
054    
055        //
056        // sorting collections of non-objects
057        //
058    
059        public static void sort (Sortable2 a) {
060            sort (a, 0, a.size()-1);
061        }
062    
063        public static void sort (Sortable2 a, int p, int r) {
064            if (p < r) {
065                int q = partition (a, p, r);
066                sort (a, p, q);
067                sort (a, q+1, r);
068            }
069        }
070    
071        private static int partition (Sortable2 a, int p, int r) {
072            int x = p + Math.abs (random.nextInt () % (r-p+1));
073            int i = p-1;
074            int j = r+1;
075    
076            while (true) {
077                do j = j-1;
078                while (a.compare (j, x) > 0);
079                do i = i+1;
080                while (a.compare (i, x) < 0);
081                if (i < j) {
082                    a.swap (i, j);
083                    if (x == i)
084                        x = j;
085                    else if (x == j)
086                        x = i;
087                } else return j;
088            }
089        }
090    
091    
092        //
093         // sorting linked lists
094        //
095    
096        public static SortableList sort (SortableList l, int n) {
097            return sort (l, n, null);
098        }
099    
100        public static SortableList sort (SortableList l) {
101            int n = 0;
102            for (SortableList p = l; p != null; p = p.next ())
103                ++n;
104            return sort (l, n);
105        }
106    
107        private static SortableList sort (SortableList l, int n, SortableList tail) {
108            if (l == null)
109                return tail;
110    
111            SortableList headLT = null, tailLT = null;
112            SortableList headGT = null, tailGT = null;
113            SortableList headEQ = null, tailEQ = null;
114            int nLT = 0, nGT = 0;
115            int pivotIndex = random.nextInt () % n;
116            SortableList pivot = traverse (l, pivotIndex);
117            while (l != null) {
118                int c = l.compareTo (pivot);
119                if (c == 0) {
120                    if (tailEQ == null)
121                        headEQ = tailEQ = l;
122                    else {
123                        tailEQ.setNext (l);
124                        tailEQ = l;
125                    }
126                }
127                else if (c < 0) {
128                    ++nLT;
129                    if (tailLT == null)
130                        headLT = tailLT = l;
131                    else {
132                        tailLT.setNext (l);
133                        tailLT = l;
134                    }
135                }
136                else {
137                    ++nGT;
138                    if (tailGT == null)
139                        headGT = tailGT = l;
140                    else {
141                        tailGT.setNext (l);
142                        tailGT = l;
143                    }
144                }
145    
146                SortableList next = l.next ();
147                l.setNext (null);
148                l = next;
149            }
150    
151            if (headEQ == null)
152                return sort (headLT, nLT, sort (headGT, nGT, tail));
153            else {
154                tailEQ.setNext (sort (headGT, nGT, tail));
155                return sort (headLT, nLT, headEQ);
156            }
157        }
158    
159        private static SortableList traverse (SortableList l, int n) {
160            while (n > 0) {
161                l = l.next ();
162                --n;
163            }
164            return l;
165        }
166    
167    
168    }