La soluzione migliore sarebbe lungo le linee di qsort di C, che consente di specificare le funzioni per confrontare e scambiare, in modo da qsort bisogno di non essere a conoscenza del tipo o di organizzazione dei dati da ordinare. Eccone uno che puoi provare. Poiché Java non ha funzioni, utilizzare la classe interna Array per avvolgere l'array o la raccolta da ordinare. Quindi avvolgilo in un IndexArray e ordina. Il risultato di getIndex() su IndexArray sarà un array di indici come descritto in JavaDoc.
public class QuickSortArray {
public interface Array {
int cmp(int aindex, int bindex);
void swap(int aindex, int bindex);
int length();
}
public static void quicksort(Array a) {
quicksort(a, 0, a.length() - 1);
}
public static void quicksort(Array a, int left, int right) {
if (right <= left) return;
int i = partition(a, left, right);
quicksort(a, left, i-1);
quicksort(a, i+1, right);
}
public static boolean isSorted(Array a) {
for (int i = 1, n = a.length(); i < n; i++) {
if (a.cmp(i-1, i) > 0)
return false;
}
return true;
}
private static int mid(Array a, int left, int right) {
// "sort" three elements and take the middle one
int i = left;
int j = (left + right)/2;
int k = right;
// order the first two
int cmp = a.cmp(i, j);
if (cmp > 0) {
int tmp = j;
j = i;
i = tmp;
}
// bubble the third down
cmp = a.cmp(j, k);
if (cmp > 0) {
cmp = a.cmp(i, k);
if (cmp > 0)
return i;
return k;
}
return j;
}
private static int partition(Array a, int left, int right) {
int mid = mid(a, left, right);
a.swap(right, mid);
int i = left - 1;
int j = right;
while (true) {
while (a.cmp(++i, right) < 0)
;
while (a.cmp(right, --j) < 0)
if (j == left) break;
if (i >= j) break;
a.swap(i, j);
}
a.swap(i, right);
return i;
}
public static class IndexArray implements Array {
int[] index;
Array a;
public IndexArray(Array a) {
this.a = a;
index = new int[a.length()];
for (int i = 0; i < a.length(); i++)
index[i] = i;
}
/**
* Return the index after the IndexArray is sorted.
* The nested Array is unsorted. Assume the name of
* its underlying array is a. The returned index array
* is such that a[index[i-1]] <= a[index[i]] for all i
* in 1..a.length-1.
*/
public int[] index() {
int i = 0;
int j = index.length - 1;
while (i < j) {
int tmp = index[i];
index[i++] = index[j];
index[j--] = tmp;
}
int[] tmp = index;
index = null;
return tmp;
}
@Override
public int cmp(int aindex, int bindex) {
return a.cmp(index[aindex], index[bindex]);
}
@Override
public void swap(int aindex, int bindex) {
int tmp = index[aindex];
index[aindex] = index[bindex];
index[bindex] = tmp;
}
@Override
public int length() {
return a.length();
}
}
anche se sono stati messi in JDK, qualcosa che ho davvero dubbio avrei mai accadere, sarebbe finiscono per essere un metodo di utilità statica della classe Array (o qualcosa di simile) e finirebbe per essere implementato molto simile a qualcosa di seguito. Allora, perché non puoi semplicemente scrivere la funzione? – Jherico
Qual è il problema con un comparatore personalizzato come soluzione? Potrei fraintendere l'approccio che questo implica nella tua mente. – jerryjvl
Forse non sto guardando abbastanza bene, ma per quello che so non c'è modo di usare un comparatore senza inscatolare ogni elemento su ogni chiamata al comparatore. Per un array di n float significherebbe 2 * n * log (n) Floats per il garbage collector. Con n = 10000 significa 80000 pezzi di immondizia. Preferirei molto un metodo di utilità statico nella classe Array. Se non mi importava della spazzatura, avrei potuto usare una TreeMap o qualcosa del genere. –