Mercurial > hg4j
comparison src/org/tmatesoft/hg/internal/ArrayHelper.java @ 307:2f2ab5c27f41
Collect sort reverse indexes along with array sorting
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Sat, 24 Sep 2011 04:06:27 +0200 |
parents | |
children | 237de162be28 |
comparison
equal
deleted
inserted
replaced
306:971baa95fb07 | 307:2f2ab5c27f41 |
---|---|
1 /* | |
2 * Copyright (c) 2011 TMate Software Ltd | |
3 * | |
4 * This program is free software; you can redistribute it and/or modify | |
5 * it under the terms of the GNU General Public License as published by | |
6 * the Free Software Foundation; version 2 of the License. | |
7 * | |
8 * This program is distributed in the hope that it will be useful, | |
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 * GNU General Public License for more details. | |
12 * | |
13 * For information on how to redistribute this software under | |
14 * the terms of a license other than GNU General Public License | |
15 * contact TMate Software at support@hg4j.com | |
16 */ | |
17 package org.tmatesoft.hg.internal; | |
18 | |
19 /** | |
20 * | |
21 * @author Artem Tikhomirov | |
22 * @author TMate Software Ltd. | |
23 */ | |
24 public class ArrayHelper { | |
25 private int[] reverse; | |
26 | |
27 @SuppressWarnings("unchecked") | |
28 public void sort(Comparable<?>[] a) { | |
29 // Object[] aux = (Object[]) a.clone(); | |
30 reverse = new int[a.length]; | |
31 sort1((Comparable<Object>[])a, 0, a.length); | |
32 } | |
33 | |
34 private void sort1(Comparable<Object> x[], int off, int len) { | |
35 // Insertion sort on smallest arrays | |
36 if (len < 7) { | |
37 for (int i=off; i<len+off; i++) | |
38 for (int j=i; j>off && x[j-1].compareTo(x[j]) > 0; j--) | |
39 swap(x, j, j-1); | |
40 return; | |
41 } | |
42 | |
43 // Choose a partition element, v | |
44 int m = off + (len >> 1); // Small arrays, middle element | |
45 if (len > 7) { | |
46 int l = off; | |
47 int n = off + len - 1; | |
48 if (len > 40) { // Big arrays, pseudomedian of 9 | |
49 int s = len/8; | |
50 l = med3(x, l, l+s, l+2*s); | |
51 m = med3(x, m-s, m, m+s); | |
52 n = med3(x, n-2*s, n-s, n); | |
53 } | |
54 m = med3(x, l, m, n); // Mid-size, med of 3 | |
55 } | |
56 Comparable<Object> v = x[m]; | |
57 | |
58 // Establish Invariant: v* (<v)* (>v)* v* | |
59 int a = off, b = a, c = off + len - 1, d = c; | |
60 while(true) { | |
61 while (b <= c && x[b].compareTo(v) <= 0) { | |
62 if (x[b] == v) | |
63 swap(x, a++, b); | |
64 b++; | |
65 } | |
66 while (c >= b && x[c].compareTo(v) >= 0) { | |
67 if (x[c] == v) | |
68 swap(x, c, d--); | |
69 c--; | |
70 } | |
71 if (b > c) | |
72 break; | |
73 swap(x, b++, c--); | |
74 } | |
75 | |
76 // Swap partition elements back to middle | |
77 int s, n = off + len; | |
78 s = Math.min(a-off, b-a ); vecswap(x, off, b-s, s); | |
79 s = Math.min(d-c, n-d-1); vecswap(x, b, n-s, s); | |
80 | |
81 // Recursively sort non-partition-elements | |
82 if ((s = b-a) > 1) | |
83 sort1(x, off, s); | |
84 if ((s = d-c) > 1) | |
85 sort1(x, n-s, s); | |
86 } | |
87 | |
88 /** | |
89 * Swaps x[a .. (a+n-1)] with x[b .. (b+n-1)]. | |
90 */ | |
91 private void vecswap(Object[] x, int a, int b, int n) { | |
92 for (int i=0; i<n; i++, a++, b++) { | |
93 swap(x, a, b); | |
94 } | |
95 } | |
96 | |
97 /** | |
98 * Returns the index of the median of the three indexed integers. | |
99 */ | |
100 private static int med3(Comparable<Object>[] x, int a, int b, int c) { | |
101 return (x[a].compareTo(x[b]) < 0 ? | |
102 (x[b].compareTo(x[c]) < 0 ? b : x[a].compareTo(x[c]) < 0 ? c : a) : | |
103 (x[b].compareTo(x[c]) > 0 ? b : x[a].compareTo(x[c]) > 0 ? c : a)); | |
104 } | |
105 | |
106 | |
107 /** | |
108 * @return the reverse | |
109 */ | |
110 public int[] getReverse() { | |
111 return reverse; | |
112 } | |
113 | |
114 /** | |
115 * Swaps x[a] with x[b]. | |
116 */ | |
117 private void swap(Object[] x, int a, int b) { | |
118 Object t = x[a]; | |
119 x[a] = x[b]; | |
120 x[b] = t; | |
121 int z1 = reverse[a] != 0 ? reverse[a] : a+1; | |
122 int z2 = reverse[b] != 0 ? reverse[b] : b+1; | |
123 reverse[b] = z1; | |
124 reverse[a] = z2; | |
125 } | |
126 } |