Come utilizzare un Heapsort in Java

April 12

L'algoritmo heapsort è uno degli algoritmi più veloce ordinamento disponibili. I programmatori heapsort utilizzano in Java, perché è una buona scelta per le matrici molto grandi che sanno di essere in uno stato indifferenziato. Per ragioni di efficienza, una struttura ad albero reale non viene utilizzato. Al contrario, l'albero si forma sul posto, proprio nella matrice. L'algoritmo heapsort è un algoritmo "al posto", in quanto non richiede memoria per eseguire l'ordinamento.

istruzione

1 Comporre il metodo di swap. In questo modo scambiare due elementi di un array. ""public static void swap(int[] a, int i, int j) {
int tmp = a[j];
a[j] = a[i];
a[i] = tmp;
}""
""public static void swap(int[] a, int i, int j) {
int tmp = a[j];
a[j] = a[i];
a[i] = tmp;
}""

2 I core dell'algoritmo, il metodo siftDown. E 'utilizzato sia per formare la struttura heap e fare il tipo reale.

3 Setacciare valori grandi verso la radice dei valori albero e piccole verso le foglie con il metodo siftDown. Poiché questo metodo viene chiamato più volte durante il processo di sequenziazione, il nodo più grande è costantemente setacciata al nodo radice e spostato alla fine della matrice. Qualsiasi nodo n ha fino a due bambini, i cui indici sono n

2 + 1 e n 2 + 2 ""public static void siftDown(int[] a, int start, int end) {
int root = start;

while( root 2 + 1 <= end ) {
int child = root
2 + 1;

// If the child has a sibling and the child's value is less than its sibling
if( child < end && a[child] < a[child + 1] ) {
child++;
}

if( a[root] < a[child] ) {
swap(a, root, child);
root = child;
} else {
return;
}
}
}""
""public static void siftDown(int[] a, int start, int end) {
int root = start;

while( root 2 + 1 <= end ) {
int child = root
2 + 1;

// If the child has a sibling and the child's value is less than its sibling
if( child < end && a[child] < a[child + 1] ) {
child++;
}

if( a[root] < a[child] ) {
swap(a, root, child);
root = child;
} else {
return;
}
}
}""

4 Utilizzare il metodo heapify. Questo metodo viene chiamato all'inizio del genere per creare la struttura iniziale mucchio. Questo è fatto rapidamente, poiché la struttura heap è alquanto vago. L'unico requisito è che ogni nodo radice deve essere superiore ai nodi figlio. ""public static void heapify(int[] a) {
for( int start = a.length / 2--1; start >= 0; start-- )
siftDown(a, start, a.length-1);
}""
""public static void heapify(int[] a) {
for( int start = a.length / 2--1; start >= 0; start-- )
siftDown(a, start, a.length-1);
}""


5 Scrivi il metodo heapsort. Il metodo prima heapifies l'array di prepararsi per l'ordinamento. Il metodo siftDown viene poi chiamato di nuovo dal momento che il nodo principale è ora un valore piccolo. Questo setaccia un nuovo valore elevato al nodo radice, e l'intero processo viene ripetuto fino a quando la dimensione del mucchio è uno. ""public static void heapSort(int[] a) {
heapify(a);

for( int end = a.length--1; end > 1; end--) {
swap(a, end, 0);
siftDown(a, 0, end--1);
}
}""
""public static void heapSort(int[] a) {
heapify(a);

for( int end = a.length--1; end > 1; end--) {
swap(a, end, 0);
siftDown(a, 0, end--1);
}
}""

6 Testare il metodo heapsort. L'esempio seguente mostra un piccolo programma di test. ""public static void main(String[] args) {
int[] a = new int[10];

for( int i = 0; i < 10; ++i ) a[i] = i+1;
for( int i = 0; i < 10; ++i )
swap(a, i, i + (int) (Math.random() * (9--i)));

System.out.println("Before sorting:");
for( int i = 0; i < a.length; ++i ) System.out.println(a[i]);

heapSort(a);
System.out.println("After sorting");
for( int i = 0; i < a.length; ++i ) System.out.println(a[i]);
}""
""public static void main(String[] args) {
int[] a = new int[10];

for( int i = 0; i < 10; ++i ) a[i] = i+1;
for( int i = 0; i < 10; ++i )
swap(a, i, i + (int) (Math.random() * (9--i)));

System.out.println("Before sorting:");
for( int i = 0; i < a.length; ++i ) System.out.println(a[i]);

heapSort(a);
System.out.println("After sorting");
for( int i = 0; i < a.length; ++i ) System.out.println(a[i]);
}""

Consigli e avvertenze

  • Anche se heapsort non viene utilizzato più spesso in Java come quicksort (perché quicksort è, in media, più veloce), il heapsort ha uno scenario più veloce nel peggiore dei casi. Dove caso peggiore del quicksort è O (n ^ 2), caso peggiore di heapsort è O (n
  • log (n)).
  • Poiché il metodo siftDown setaccia i valori più grandi all'inizio del mucchio (indice di matrice 0), ad ogni iterazione del genere il nodo radice viene scambiato con l'ultimo nodo foglia, e la dimensione del cumulo viene decrementato. Questo è come l'ordinamento attuale è fatto, setacciando i valori grandi per la parte superiore e spostandole fino alla fine.
  • Utilizzando una struttura ad albero reale sarebbe generare un sacco di nuovi oggetti, mettere il carico sulla allocatore e garbage collector, utilizzare più memoria e prendere più accessi alla memoria.