Algorytmy i Struktury Danych Wykład IV Sortowania cd. Elementarne struktury danych 1 Co dziś? Dolna granica sortowań Mediany i statystyki pozycyjne Warstwa implementacji Warstwa abstrakcji #tablice #listy #stos, kolejki 2 Drzewo decyzyjne A[1]:A[2] > A[2]:A[3] A[1]:A[3] 1,2,3 A[1]:A[3] 2,1,3 A[2]:A[3] 1,3,2 3,1,2 2,3,1 3,2,1 3 1
Minimum i maksimum min lub max -liniowe przeszukanie O(n) #n-1 porównań min i max linowe przeszukanie O(n) #2n-2 porównań #3(n/2) -porówań 4 Wybór i tego elementu Algorytm Hoare a # oczekiwany czas liniowy Algorytm magicznych piątek # pesymistyczny czas liniowy 1. podziel n elementów na zbiory 5 elementowe 2. wyznacz medianę z każdej piątki 3. wywołaj rekurencyjnie dla znalezienia mediany median 4. podziel tablicę względem znalezionej mediany 5. wywołaj rekurencyjnie dla mniejszych lub większych elementów 5 Warstwa implementacji Możliwości # tablica # wskaźniki (odsyłacze, pointery) # obiekty (referencje) Deklaracje # statyczne # dynamiczne Różnice # szybkość # rodzaje pamięci # moment alokacji 6 2
Tablica Tablica statyczna Tablica dynamiczna #realokacja Złożoność # O(1) <-> O(n) Indeks to liczby całkowite -> arytmetyka na pointerach + rzutowanie Ograniczenia #deklaracja #dostępna pamięć 7 int taba[10]; int * tabb = (int*)malloc( 10 * sizeof (int) ); int * tabc = new int[10]; tabb = (int*)realloc( tabb, 20 * sizeof (int) ); taba[0] = *(taba + 0); free( tabb ); delete []tabc; Wskaźniki Lista (łańcuch odsyłaczowy) # jednokierunkowa # dwukierunkowa # cykliczna # z wartownikami # drzewa Złożoność # listy O(1) <-> O(n) # drzewa O(1) <-> O(log(n)) <-> O(n) Ograniczenia # dostępna pamięć 9 3
Wskaźniki 10 Wskaźniki 11 Wskaźniki - wartownik 12 4
void foo( pele * head )... void foo( pele ** head )... void foo( pele *& head ) pele * foo( pele * head )... // tail, root void foo( pele * firstele )... while( ele )... while( ele->next )... if ( ele && ele->key ==??? while ( ele && ele->key ==??? if ( ele && ele->next... Drzewa 14 bool foo( pnode * node ) if ( node->key ==??? if ( node->left ) return foo( node->left ); if ( node->right ) return foo( node->right ); if ( node->left ) i = foo( node->left ); if ( node->right ) i += foo( node->right ); 5
Drzewo? 16 Drzewo? 17 Inne 18 6
Inne 19 Inne 20 Warstwa abstrakcji Abstrakcyjne struktury danych struktury # tablica lub wskaźniki #dodatkowe elementy indeks maksymalny, indeks bieżący głowa listy, ogon, element wyróżniony Interfejs struktury # metody, funkcje, operatory #zachowanie 21 7
Warstwa abstrakcji Rodzaje metod # zapytania # operacje modyfikujące Dane i klucz Rozpatrywanie złożoności dopiero przy implementacji jednaj struktury przy pomocy zaimplementowanego interfejsu innej struktury # kolejka priorytetowa -> kopiec -> tablica 22 Metody uniwersalne #search( key ), search( x ) #insert( x ) #delete( x ) #min() #max() #successor( x ) #predecessor( x ) 23 Tablica # set # get # size # bezpośredni dostęp do każdego elementu, określona długość(?) # tablica # lista jedno (dwu) kierunkowa 24 8
Lista jednokierunkowa # insert # search # delete # isempty # next # podstawowa cecha to brak ograniczenia na ilość elementów # tablica # lista jednokierunkowa 25 Lista 7 0 1 2 3 4 5 6 7 next 2 * 1 4 key 34 22 12 56 prev 4 1 7 * 6 34 * 12 22 3 * 12 6 26 Stos (LIFO) # push # pop # isempty # element ostatnio położony jest pierwszy ściągany, kładziemy elementy na wierzchołek stosu i z niego ściągamy # tablica # lista jednokierunkowa 27 9
Kolejka (FIFO) # isempty # put(insert) # get(extract) # element ostatnio położony musi czekać na swoją kolej, pobieramy elementy z początku, a wstawiamy na koniec # tablica # lista jednokierunkowa, dwukierunkowa 28 Kolejka dwukierunkowa (talia) # isempty # putfirst, -last(insert, head-tail) # getfirs, -last(extract, head-tail) # wstawiamy na początek i na koniec, pobieramy elementy z początku lub z końca # tablica # lista jednokierunkowa, dwukierunkowa 29 Zbiór # add # delete # isin # union # wszystkie elementy są różne, każdy element występuje jedne raz # tablica # lista ASD 05 30 10
Zbiory rozłączne # makeset # union # findset # zbiór jest reprezentowany przez reprezentanta, reprezentantem jest korzeń, element zbioru wskazuje na swojego ojca # prosta implementacja odsyłaczowa # drzewa ukorzenione # drzewa ukorzenione + Heurystyki łączenie wg rangi kompresja ścieżki ASD 05 31 MakeSet(X x) x.parent = x; x.rank = 0; Union(X x,x y) Link( FindSet(x), FindSet(y) ); Link(x,y) if (x.rank > y.rank) y.parent = x; else x.parent = y; if (x.rank == y.rank ) y.rank++; X FindSet( X x ) if ( x.parent!= x ) x.parent = FindSet(x.parent); return x.parent; Kolejka priorytetowa # put (insert) # get (extract) # isempty # element wstawiamy nie na koniec, ale w zależności od key # lista O(n) # tablica posortowana O(n) # kopiec O(log(n)) ASD 05 33 11
void heap(int i) int l = 2 * i + 1; int r = 2 * i + 2; int maxi,t; if ( l < max && A[l] > A[i] ) // MAX maxi = l; else maxi = i; if ( r < max && A[r] > A[maxi] ) maxi = r; if ( maxi!= i ) t = A[i]; A[i] = A[maxi]; A[maxi] = t; heap( maxi ); void heap(int i) while(1) int l = 2 * i + 1; int r = 2 * i + 2; int maxi,t; if ( l < max && A[l] > A[i] ) maxi = l; else maxi = i; if ( r < max && A[r] > A[maxi] ) maxi = r; if ( maxi!= i ) t = A[i]; A[i] = A[maxi]; A[maxi] = t; i = maxi; else break; int put( int ele ) if ( max + 1 == MAX ) // == return error; //??? int i = max++; while( i > 0 && A[(i-1)/2] < ele ) A[i] = A[(i-1)/2]; i = (i-1)/2; A[i] = ele; 12
class Heap protected: data* A; int max; public: data get(); void put(data a); Heap(); ~Heap(); data Heap::get() if ( max == 0 ) // return error;??? throw errorheapemptyexception; data ret = A[0]; A[0] = A[--max]; heap( 0 ); return data; Jeszcze o kopcu Kopiec binarny Kopiec rzędu d #d-arny #zamiast 2 synów, każdy węzeł ma ich d Złożoność struktury #O( log(n)) == O( log d (n)) # szybkość vs łatwość implementacji ASD 05 39 13
Pytania? KONIEC 40 14