plik


Algorytmy i struktury danych Informatyka, sem IV Wykład 4: Sortowanie 1. Proste algorytmy sortowania (złożoność O(n*n) ) Makro do zamiany dwoch el. wektora double: #define swap( V, i, j ) { double tmp= (v)[(i)]; (v)[(i)]= (v)[(j)]; (v)[(j)]= tmp; } 1.1. Sortowanie bąbelkowe void bublesort( double v[], int n ) { int bylazamiana; do { register int i; bylazamiana= 0; for( i= 1; i < n; i++ ) if( v[i] < v[i-1] ) { swap( v, i, i-1 ); bylazamiana= 1; } } while( bylazamiana ); } 1.2. Sortowanie przez wybieranie void choosesort( double v[], int n ) { register int i,j; for( i= 0; i < n-1; i++ ) { register int min= i; for( j= i+1; j < n; j++ ) if( v[j] < v[min] ) min= j; swap( v, i, min ); } } 1.3 Sortowanie przez wstawianie void insertsort( double v[], int n ) { register int i,j; for( i= 1; i < n; i++ ) { double tmp= v[i]; for( j= i-1; j >= 0 && v[j] > tmp; j-- ) v[j+1]= v[j]; v[j+1]= tmp; } } 1.4 Sortowanie Shella void shellsort( double v[], int n ) { register int i,j; register int gap= 1; while( gap <= n/9 ) gap= 3*gap + 1; /* Ustalamy maks. gap - ciag zalecany przez Knuth'a dla n <= 1000 */ for( ; gap >= 1; gap /= 3 ) for( i= gap; i < n; i++ ) { double tmp= v[i]; for( j= i-gap; j >= 0 && v[j] > tmp; j-= gap ) v[j+gap]= v[j]; v[j+gap]= tmp; } } Czy to sortuje ? Prosze zwrocic uwage, iż dwie wewnętrzne pętle for to uogolniona wersja alg. przez wstawianie. A więc, w najgorszym wypadku Shellsort to insertsort. Ulepszenie polega na tym, ze w pierwszych przebiegach (dla dużych wart. gap) porownywane (i ew. zamieniane) są odległe elementy. W dalszych przebiegach pozostaje juz niewiele do zrobienia. 2. Algorytmy optymalne (złożoność O(n*log_2(n))) 2.1 Sortowanie szybkie (najlepszy znany algorytm oparty na porównywaniu elementów) int rozdziel( double a[], int s, int k ) { /* rozdziela wektor a wzgledem a[0], zwraca pozycje a[0] w wektorze wynikowym */ int i, j; double tmp; j= s; for( i= s+1; i <= k; i++ ) /* niezmiennik: a[s+1..j] < a[s] i a[j+1..i-1] >= a[s] */ if( a[i] < a[j] ) { tmp= a[++j]; a[j]= a[i]; a[i]= tmp; } tmp= a[j]; a[j]= a[s]; a[s]= tmp; return j; } void mqsort( double a[], int s, int k ) { /* sortuje in situ, rosnaco a[s..k] */ if( s < k ){ int j= rozdziel( a, s, k ); mqsort( a, s, j-1 ); mqsort( a, j+1, k ); } } void quicksort( double a[], int na ) { mqsort( a, 0, na-1 ); } Bez rekurencji: #define MAXS 1024 /* maksymalna gleb. stosu */ void mqsort( double a[], int s, int k ) { /* sortuje in situ, rosnaco a[s..k] */ int ss[MAXS], ks[MAXS], sp= 0; /* ss <- "poczatki", ks <- "konce" pod-wektorow */ if( s < k ){ ss[0]= s; ks[0]= k; sp= 1; while( sp ) { int bs= ss[--sp]; int bk= ks[sp]; int j= rozdziel( a, bs, bk ); if( j-1 > bs ) { ss[sp]= bs; ks[sp++]= j-1; } if( k > j+1 ) { ss[sp]= j+1; ks[sp++]= bk; } } } } 2.2 Sortowanie stogowe Zagadnienia wstępne: - pojecie stogu; - implementacja tablicowa; typedef struct { Data d; /* jakiekolwiek dane */ int key; /* klucz porządkujący */ } Elem; typedef Elem * Heap; /* stog jest tablica elementów */ #define swap( h, i, j ) { Elem tmp= (h)[(i)]; (h)[(i)]= (h)[(j)]; (h)[(j)]= tmp; } - wstawianie nowego elementu: dodanie na koniec i przesiewanie w górę (funkcja "do góry" o koszcie O(log_2(n))) void heap_up( Heap s, int n ) { int i= n; int p= (i-1)/2; while ( i > 0 && s[p].key > s[i].key ) { swap( s, p, i ); i= p; p= (i-1)/2; } } - usuwanie szczytowego elementu: zastąpienie go ostatnim i przesiewanie w dół (funkcja "na dół" o koszcie O(log_2(n))) void heap_down( Heap s, int n ) { int p= 0; int d= 2*p+1; while ( d < n ) { if( d+1 < n && s[d+1].key < s[d].key ) d++; if( s[p].key < s[d].key ) return; swap( s, p, d ); p= d; d= 2*p+1; } } Teraz sortowanie stogowe, zrobione analogicznie do standardowego qsort-a (potrafi sortowac dowolne tablice). void hsort(void *t, int n, size_t s, int (* cmpf)(const void *, const void *)) { int i; int b, p; char *tmp = malloc(s); char *v = t; int k; for (i = 1; i < n; i++) { /* dogory(t[i]... */ b = i; p = (n-1)/2; while (cmpf(v+p*s, v+b*s) < 0) { memcpy(tmp, v+p*s, s); memcpy(v+p*s, v+b*s, s); memcpy(v+b*s, tmp, s); b = p; p = (b-1)/2; } for (k = 0; k <= i; k++) printf("%g ", *(float *)(v+k*s)); printf("\n"); } for (i = 0; i < n; i++) printf("%g ", *(float *)(v+i*s)); printf("\n"); for (i = n-1; i > 0; i--) { memcpy(tmp, v, s); memcpy(v, v+i*s, s); memcpy(v+i*s, tmp, s); b = 0; p = 2*b+1; while (p < n) { if (p+1 < n && cmpf(v+(p+1)*s, v+p*s) > 0) p++; if (cmpf(v+p*s, v+b*s) <= 0) break; memcpy(tmp, v+p*s, s); memcpy(v+p*s, v+b*s, s); memcpy(v+b*s, tmp, s); b = p; p = 2*b+1; } } } Zagadnienia dodatkowe: - wykorzystanie stogu do implementacji kolejki priorytetowej - scalanie posortowanych plików (ciągów danych) => wykład z j. C

Wyszukiwarka

Podobne podstrony:
Algorytmy I Struktury Danych (Wyklady) info
Algorytmy i struktury danych Wyklad 3
Algorytmy i struktury danych (wykłady)
Algorytmy i struktury danych Wyklad 1
Algorytmy i struktury danych Wyklad 2
Algorytmy i struktury danych Programy do wykladu 3
Algorytmy i struktury danych Prosty program Simulated Annealing
notatek pl W,matematyka,Algorytmy i Struktury Danych
Algorytmy i struktury danych all
Algorytmy i struktury danych rot
Algorytmy i struktury danych 04 Listy
Algorytmy i Struktury Danych
Algorytmy i struktury danych 02 Rekurencja i złożoność obliczeniowa

więcej podobnych podstron