Algorithmensammlung: Sortierverfahren: Heapsort
Aus Wikibooks
Algorithmensammlung: Sortierverfahren
-
- Combsort
- Quicksort
- Heapsort
- Selectionsort
Inhaltsverzeichnis |
[Bearbeiten] Heapsort
Heapsort ist ein Sortieralgorithmus, der die Datenstruktur der
Halde ausnutzt, um in-place zu sortieren. Der Algorithmus ist dabei auch im Worst-Case in der Komplexitätsklasse
und damit in diesem Fall schneller als Quicksort.
Für weitere Informationen siehe
Heapsort.
[Bearbeiten] C++
#include <iterator> template< typename Iterator > void adjust_heap( Iterator first , typename std::iterator_traits< Iterator >::difference_type current , typename std::iterator_traits< Iterator >::difference_type size , typename std::iterator_traits< Iterator >::value_type tmp ) { typedef typename std::iterator_traits< Iterator >::difference_type diff_t; diff_t top = current, next = 2 * current + 2; for ( ; next < size; current = next, next = 2 * next + 2 ) { if ( *(first + next) < *(first + next - 1) ) --next; *(first + current) = *(first + next); } if ( next == size ) *(first + current) = *(first + size - 1), current = size - 1; for ( next = (current - 1) / 2; top < current && *(first + next) < tmp; current = next, next = (current - 1) / 2 ) { *(first + current) = *(first + next); } *(first + current) = tmp; } template< typename Iterator > void pop_heap( Iterator first, Iterator last) { typedef typename std::iterator_traits< Iterator >::value_type value_t; value_t tmp = *--last; *last = *first; adjust_heap( first, 0, last - first, tmp ); } template< typename Iterator > void heap_sort( Iterator first, Iterator last ) { typedef typename std::iterator_traits< Iterator >::difference_type diff_t; for ( diff_t current = (last - first) / 2 - 1; current >= 0; --current ) adjust_heap( first, current, last - first, *(first + current) ); while ( first < last ) pop_heap( first, last-- ); }
[Bearbeiten] Java
/** * sortiert ein Array mit heapsort * @param a das array */ private static void heapSort(int[] a) { generateMaxHeap(a); //hier wird sortiert for(int i = a.length -1 ; i > 0 ; i--) { vertausche(a, i, 0); versenke(a, 0,i); } } /** * Erstellt einen MaxHeap Baum im Array * @param a das array */ private static void generateMaxHeap(int[] a) { //starte von der Mitte rückwärts. for(int i = (a.length / 2) - 1; i >= 0 ; i--) { versenke(a,i,a.length); } } /** * versenkt ein element im baum * @param a Das Array * @param i Das zu versenkende Element * @param n Die letzte Stelle im Baum die beachtet werden soll */ private static void versenke(int[] a, int i,int n) { while(i <= (n / 2) - 1) { int kindIndex = ((i+1) * 2) - 1; // berechnet den Index des linken kind //bestimme ob ein rechtes Kind existiert if(kindIndex + 1 <= n -1) { //rechtes kind existiert if(a[kindIndex] < a[kindIndex+1]) { kindIndex++; // wenn rechtes kind größer ist nimm das } } //teste ob element sinken muss if(a[i] < a[kindIndex]) { vertausche(a,i,kindIndex); //element versenken i = kindIndex; // wiederhole den vorgang mit der neuen position } else break; } } /** * Vertauscht die arraypositionen von i und kindIndex * @param a Das Array in dem getauscht wird * @param i der erste index * @param kindIndex der 2. index */ private static void vertausche(int[] a, int i, int kindIndex) { int z = a[i]; a[i] = a[kindIndex]; a[kindIndex] = z; }
[Bearbeiten] Pascal
const SIZE = 20000; type TFeld = array[1..SIZE] of integer; procedure heapsort(var f:TFeld); procedure genheap(var f:TFeld); { Heap (mit linearem Aufwand) aufbauen } var i,j,max,temp:integer; begin for i := SIZE div 2 downto 2 do begin { zweite Hälfte des Feldes braucht nicht betrachtet werden } j:=i; while j <= SIZE div 2 do begin max := j * 2 + 1; { finde Maximum der (beiden) Söhne } if max > SIZE then dec(max) else if f[max-1] > f[max] then dec(max); if f[j] < f[max] then begin { ggf. tauschen } temp := f[j]; f[j] := f[max]; f[max] := temp; end; j := max; end; end; end; function popmax(var f:TFeld;heapsize:integer):integer; var i,max,temp:integer; begin popmax := f[1]; f[1] := f[heapsize]; i := 1; while i <= (heapsize div 2) do begin { letztes Element an Anfang setzen und versickern lassen } max := i * 2 + 1; { finde Maximum der (beiden) Söhne } if max > heapsize then dec(max) else if f[max-1] > f[max] then dec(max); if f[i] < f[max] then begin { ggf. tauschen } temp := f[i]; f[i] := f[max]; f[max] := temp; end; i := max; end; end; var i:integer; begin genheap(f); for i:=SIZE downto 1 do f[i] := popmax(f,i); end;
[Bearbeiten] Python
from math import * import random class tree: # initialize tree def __init__(this,list): this.list = list # Exchange-Operation def exch(this, i,j): tmp = this.list[i] this.list[i] = this.list[j] this.list[j] = tmp # sink item # die iterative Variante frei nach Robert Sedgewick def sink(this,index): N = len(this.list) k = index+1 while(2*k <= N): j=2*k if j<N and this.list[j-1] < this.list[j]: j += 1 if this.list[k-1] >= this.list[j-1]: break this.exch(k-1,j-1) k = j def getHighest(this): a = this.list[0] this.exch(0,len(this.list)-1) del this.list[len(this.list)-1] this.sink(0) return a # Generating random numbers a = [] for i in range(0,100): a.append(random.randint(1,10000)) a = tree(a) print a.list # Build Heap tmp = range(len(a.list)) tmp.reverse() for i in tmp: a.sink(i) # UnBuild Heap to view as sorted list out = [] for i in range(len(a.list)): out.append(a.getHighest()) out.reverse() print out
[Bearbeiten] Fortran
# Die Implementierung wurde der JAVA-Version nachempfunden subroutine vertausche (a, size, x, y) integer x, y, z, size integer a(size) z = a(x) a(x) = a(y) a(y) = z return end subroutine versickere (a, size, i) integer i, size, ln, j integer a(size) j = i do while (j.LE.(size/2)) ln = 2*j if (ln.LT.size) then if ((a(ln+1)).GT.(a(ln))) ln = ln+1 end if if ((a(ln)).GT.(a(j))) then call vertausche(a,Size,j,ln) j = ln else j = size end if end do return end subroutine ueberfuehreInHeap (a, size) integer size, i integer a(size) do i = size /2 , 1 , -1 call versickere (a, size, i) end do return end subroutine heapSort (a, size) integer size integer a(size) call ueberfuehreInHeap(a,size) do i=size, 1, -1 call vertausche(a, size, 1, i) call versickere(a, i-1, 1) end do return end