Wykłady opracowane zostały w oparciu o materiały prof. dr hab. Jerzego Weresa Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 2
Struktura danych (ang. data structure) sposób uporządkowania informacji w komputerze. Na strukturach danych operują algorytmy. Przykładowe struktury danych to: rekord, zwany w niektórych językach po prostu strukturą (ang. struct, record), logiczny odpowiednik to krotka, tablica, lista, stos, kolejka, drzewo i jego liczne odmiany (np. drzewo binarne), graf. Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 3
Podczas implementacji programu programista często staje przed wyborem między różnymi strukturami danych, aby uzyskać pożądany efekt. Odpowiedni wybór może zmniejszyć złożoność obliczeniową, ale z drugiej strony trudność implementacji danej struktury może stanowić istotną przeszkodę. Ponieważ struktury danych są w programie rzeczą szczególnie istotną, wiele języków programowania wspiera programistę, dostarczając bibliotekę standardową z zaimplementowanymi różnorodnymi strukturami danych. Można tu wymienić Standard Template Library w C++, APIjęzyka Java oraz platformę.net. Próbą połączenia idei struktur danych i algorytmów jest pomysł programowania obiektowego. Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 4
Typ w językach programowania opis rodzaju, struktury i zakresu wartości, jakie może przyjmować dany literał, zmienna, stała, argument, wynik funkcji lub wartość. Przykładowe typywystępujące wwielujęzykach programowania: typ całkowity (w C, C++, Javie np. int,wpascalunp.integer) typ reprezentujący liczbę całkowitą z jakiegoś zakresu zależnego od języka a nawet konkretnej implementacji. typ zmiennoprzecinkowy (w C, C++, Javie np. double, w Pascalu np. real) typ reprezentujący przybliżoną wartość liczby rzeczywistej. typ znakowy (w C, C++, Javie, Pascalu np. char) typ reprezentujący pojedynczy znak (ASCII lub w nowszych implementacjach Unicode) typ tekstowy (w Javie String, w C++, Pascalu np. string) typ reprezentujący cały tekst. W C jego rolę pełni wskaźnik do literału znakowego const char* typ wskaźnikowy oznacza wskaźnik na zmienną zadanego typu. typ referencyjny odmiana wskaźnika, referencja jest różnie pojmowana w poszczególnych językach. typ wyliczeniowy typ mogący przyjmować jedną z zadanych symbolicznych wartości, np. (czerwony, zielony, niebieski) Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 5
typ tablicowy ciąg zmiennych zadanego typu indeksowanych liczbą naturalną z pewnego przedziału (w większości języków programowania) lub dowolnym unikalnym kluczem który może być zarówno liczbą jak i ciągiem znaków (w PHP) typ strukturalny zespół połączonych w jedną całość zmiennych zwanych polami struktury. Do każdego pola można się odwoływać oddzielnie. klasa (typ obiektowy) odmiana struktury, w której oprócz zespołu danych dodane są także procedury działających na tych danych. Zmienna typu klasy nazywasię obiektem.pojęcie klasy spowodowało powstanie nowego paradygmatu programowania, zwanego programowaniem obiektowym i zrewolucjonizowało sposób myślenia programisty, który od tej pory patrzy na program jako na zbiór autonomicznych obiektów. typ pusty (np. void w C i C++) występuje np. w oznaczaniu funkcji nie zwracających żadnych zmiennych. typ logiczny (np. bool wc++) może przyjmować wartości logiczne 1 (true, t) lub 0(false, nil). Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 6
Kontener danych dostępnych, w którym poszczególne komórki dostępne są za pomocą kluczy, które najczęściej przyjmują wartości numeryczne. Rozmiar tablicy jest albo ustalony z góry (tablice statyczne), albo może się zmieniać w trakcie wykonywania programu (tablice dynamiczne). W matematyce odpowiednikiem tablicy jednowymiarowej jest ciąg, a tablicy dwuwymiarowej macierz. [1,3,5,2,7,8,4] Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 7
Praktycznie wszystkie języki programowania obsługują tablice jedynie w niektórych językach funkcyjnych zamiast tablic używane są listy (choć tablicezwykleteż są dostępne). Lista to struktura danych używana w informatyce. Jest to pojemnik składający się z połączonych ze sobą w łańcuszek komórek zawierających dane. Typowa lista jest łączona jednostronnie komórki zawierają tylko odnośnik do kolejnej komórki. Innym przypadkiem jest lista dwustronna, gdzie komórki zawierają także odnośnik do poprzednika. Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 8
Popularna jest także lista zwana słownikową, która zazwyczaj jest wariacją listy jednostronnej. Z reguły stosuje się ją tam, gdzie elementy listy zawierają kilka pól z danymi, a kolejny element możerozszerzać pojęcie (definicję poprzedniego). Przykładem jest prosty translator tekstu, zrealizowany jako lista, gdzie każdy z elementów zawiera dane wyraz i definicja wyrazu możesię okazać, że definicja danego wyrazu ma swoje rozwinięcie (definicję) w pewnym innym elemencie, wówczas tam kieruje się dodatkowy łącznik. Istnieją dwie popularne implementacje struktury listy: tablicowa i wskaźnikowa. Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 9
Implementacja tablicowa Jak wskazuje nazwa, lista zaimplementowana w ten sposób opiera się na tablicy obiektów (lub rekordów) danego typu. Dopisanie elementu do listy to wstawienie elementu do tablicy: jeślimaono nastąpić na końcu listy, będzie tokolejnyelement w tablicy; jeśli nowy element ma znaleźć się między innymi elementami, należyprzesunąć ojednopole w prawo wszystkie elementy o indeksie wyższym niż pole, na które będzie wstawiany obiekt; następnie w powstałą lukę wpisuje się nowy element. Usunięcie elementu znajdującego się pod danym indeksem tablicy to przesunięcie o jedno pole w lewo wszystkich elementów o indeksie wyższym. Zalety tej implementacji: prosta nawigacja wewnątrz listy, korzystanie z gotowej struktury tablicy, szybki dostęp do elementu o konkretnym numerze, większa odporność na błędy. Wady: niska elastyczność, szczególnie dotycząca rozmiaru tablicy, złożoność operacji wstawiania i usuwania. Implementację tablicową stosuje się tam, gdzie elastyczność nie odgrywa istotnej roli, a wymagana jest szybka i prosta nawigacja. Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 10
Implementacja wskaźnikowa W tej implementacji każdy obiekt na liście musi (co nie było konieczne w wersji tablicowej) zawierać dodatkowy element: wskaźnik do innego obiektu tego typu. Wynika to z faktu, że to wskaźniki są podstawą nawigacji w tym typie listy, a dostęp do jej elementów jest możliwy wyłącznie przez wskaźnik. Dopisanie elementu (dla prostej listy jednostronnej): jeśli ma ono nastąpić na końcu listy, to wskaźnik wiążący w obiekcie ostatnim ustawia się na nowy obiekt danego typu; jeśli ma ono nastąpić wewnątrz listy, to najpierw tworzy się nowy obiekt danego typu i jego wskaźnik wiążący ustawia się na następnik elementu, za którym ma być wstawiany. Później wskaźnik poprzednika przestawia się na ten nowy obiekt. W tym przypadku bardzo ważna jest kolejność, której zachwianie jest częstą przyczyną błędów. Np. można najpierw przestawić wskaźnik poprzednika na nowy obiekt, co spowoduje bezpowrotną utratę dostępu do dalszych elementów listy, na które już nie będzie pokazywał żaden wskaźnik. Ustawienie wskaźnika nowego elementu na następnik nie będzie możliwe, bo nie będzie znany jego adres. Usunięcie elementu jest odwrotne do wstawiania: w pewnym miejscu zapisuje się wskaźnik do usuwanego elementu (aby nie "zgubić" jego adresu), następnie wskaźnik wiążący poprzednika przestawia się na następnik, i dopiero w tym momencie zwalnia się pamięć po obiekcie usuwanym (do tego potrzebny jest ten wskaźnik tymczasowy). Zalety i wady tej implementacji są komplementarne w stosunku do implementacji tablicowej. Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 11
Wgłębiając się w szczegóły implementacji listy za pomocą wskaźników można wyróżnić następujące rodzaje list: lista jednokierunkowa wkażdym elemencie listy jest przechowywane odniesienie tylko do jednego sąsiada (następnika lub poprzednika). lista dwukierunkowa wkażdym elemencie listy jest przechowywane odniesienie zarówno do następnika jak i poprzednika elementu w liście. Taka reprezentacja umożliwia swobodne przemieszczanie się po liście w obie strony. lista cykliczna następnikiem ostatniego elementu jest pierwszy element, a poprzednikiem pierwszego ostatni. Po liście można więc przemieszczać się cyklicznie. Nie ma w takiej liście charakterystycznego ogona (ani głowy), częstorozpoznawanegopotym, że jegonastępnik jest pusty (NULL). lista z wartownikiem lista z wyróżnionym elementem zwanym wartownikiem. Jest to specjalnie oznaczony element niewidoczny dla programisty wykorzystującego listę. Pusta lista zawiera wtedy tylko wartownika. Zastosowanie wartownika znacznie upraszcza implementację operacji na listach. Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 12
Stos (j. ang.: stack) jest strukturą danych, do której dostęp jest wyłącznie od strony wierzchołka (j. ang.: top) takie operacje jak położenie danych na stosie (j. ang.: push) lub zdjęcie ich (j. ang.: pop) mogą odbywać się jedynie na wierzchołku stosu. Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 13
Zasada działania stosu: LIFO (j. ang.: Last In First Out), czyli Pierwszy wychodzi ten, kto wszedł ostatni. Zastosowania stosu: wywołanie funkcji, rekurencja. Implementacja stosu: tablica indeks tablicy wskazuje na element ostatnio położony na stosie; lista jednokierunkowa wierzchołek stosu znajduje się na początku listy. Do niego są dołączanenoweelementyizniegosą elementy zdejmowane. Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 14
Podstawowe funkcje wykonywane na stosie: push (X) położenie elementu X na wierzchołku stosu, pop(x) zdjęcie elementu X z wierzchołka stosu. Funkcje te zwracają również kod błędu, stałą typu całkowitego informującą o wystąpieniu sytuacji anormalnej. push(x) pop(x) Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 15
Zasadę działania stosu można podsumować dwiema regułami: Po wykonaniu operacji push(x) węzeł X staje się nowym wierzchołkiem stosu, przykrywając poprzedni,jeśli stos nie był pusty. Jedynym bezpośrednio dostępnym węzłem jest wierzchołek stosu. Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 16
Ilustracja podstawowych operacji wykonywanych na stosie o pojemności trzech elementów: s = pop (c); s = push ('A'); s = push ('B'); s = pop (c); s = push ('C'); s = push ('D'); s = StosPusty s = OK s = OK s = OK. s = OK s = StosPełny c =?? c = 'B' A B A A C A D C A push pop połóż - zdejmij Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 17
Przykład: stos1.c #include <stdio.h> #include <stdlib.h> struct WezelStosu int dana; struct WezelStosu *nastepnywsk; ; typedef struct WezelStosu WEZELSTOSU; typedef WEZELSTOSU *WEZELSTOSUWSK; void poloz(wezelstosuwsk *, int); int zdejmij(wezelstosuwsk *); int jestpusty(wezelstosuwsk); void drukujstos(wezelstosuwsk); void polecenia(void); Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 18
main() WEZELSTOSUWSK stosuwsk = NULL; /* wskazuje na wierzcholek */ int wybor, wartosc; polecenia(); printf("? "); scanf("%d", &wybor); while (wybor!= 3) switch (wybor) case 1: /* poloz wartosc na stosie */ printf("wprowadz liczbe calkowita: "); scanf("%d", &wartosc); poloz(&stosuwsk, wartosc); drukujstos(stosuwsk); break; Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 19
case 2: /* zdejmij wartosc ze stosu */ if (!jestpusty(stosuwsk)) printf("zdjeta wartosc wynosi %d.\n", zdejmij(&stosuwsk)); drukujstos(stosuwsk); break; default: printf("zly wybor.\n\n"); polecenia(); break; printf("? "); scanf("%d", &wybor); printf("koniec pracy.\n"); return 0; Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 20
/* Wydruk polecen */ void polecenia(void) printf("wprowadz wybor:\n" "1 aby polozyc wartosc na stosie\n" "2 aby zdjac wartosc ze stosu\n" "3 aby zakonczyc program\n"); Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 21
/* Polozenie wezla na wierzcholku stosu */ void poloz(wezelstosuwsk *wierzcholekwsk, int info) WEZELSTOSUWSK nowywsk; nowywsk = malloc(sizeof(wezelstosu)); if (nowywsk!= NULL) nowywsk->dana = info; nowywsk->nastepnywsk = *wierzcholekwsk; *wierzcholekwsk = nowywsk; else printf("%d nie wstawione. Brak dostepnej pamieci.\n", info); Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 22
/* Usuniecie wezla z wierzcholka stosu */ int zdejmij(wezelstosuwsk *wierzcholekwsk) WEZELSTOSUWSK chwilowywsk; int zdejmijwartosc; chwilowywsk = *wierzcholekwsk; zdejmijwartosc = (*wierzcholekwsk)->dana; *wierzcholekwsk = (*wierzcholekwsk)->nastepnywsk; free(chwilowywsk); return zdejmijwartosc; Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 23
/* Drukowanie zawartosci stosu */ void drukujstos(wezelstosuwsk biezacywsk) if (biezacywsk == NULL) printf("stos jest pusty.\n\n"); else printf("stos zawiera:\n"); while (biezacywsk!= NULL) printf("%d --> ", biezacywsk->dana); biezacywsk = biezacywsk->nastepnywsk; printf("null\n\n"); Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 24
/* Czy stos jest pusty? */ int jestpusty(wezelstosuwsk wierzcholekwsk) return wierzcholekwsk == NULL; Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 25
Przyklad: stos2.cpp #include <conio.h> #include <stdio.h> #include <stdlib.h> #include <iostream.h> struct stos char dana[10]; stos *ref; ; stos *wskaznik; stos *stary; Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 26
void poloz_na_stos(char dodaj[10]) stary=wskaznik; wskaznik=new stos; strcpy(wskaznik->dana,dodaj); wskaznik->ref=stary; void usun_wezel(stos *wezel) if (wezel!=null) stary=wezel->ref; printf("usunieto: %s\n",wezel->dana); delete wezel; wskaznik=stary; else printf("stos jest pusty\n"); Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 27
void drukuj_zawartosc_stosu() printf("zawartosc stosu:\n"); stary=wskaznik; while (stary!=null) cout <<stary->dana<<"\n"; stary=stary->ref; void usun_wszystko(void) stary=wskaznik; while (stary!=null) usun_wezel(stary); printf("\n Stos oczyszczony. Nacisnij dowolny klawisz..."); Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 28
void main(void) char dana[10]; printf("wprowadz dana, do 10 znakow, bez spacji:\n"); printf(" # - zdejmij dana ze stosu, \n"); printf(" $ - wypisz zawartosc stosu,\n"); printf(" & - usun wszystko i zakoncz prace\n"); Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 29
do printf("dana: "); scanf("%s",&dana); if (strcmp(dana,"&")!=0) if (strcmp(dana,"#")==0) usun_wezel(wskaznik); else if (strcmp(dana,"$")==0) drukuj_zawartosc_stosu(); else poloz_na_stos(dana); while (strcmp(dana,"&")!=0); usun_wszystko(); getch(); Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 30
Kolejki są strukturą danych o ograniczonym dostępie, zgodnie z zasadą FIFO (j. ang.: First In First Out), czyli Pierwszy wychodzi ten, kto pierwszy wszedł. Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 31
Zawartość kolejki stanowią węzły (elementy) pomiędzy głową (czołem) a ogonem. Podstawowe operacje dotyczące kolejki: wstaw (enqueue) wstaw dane na ogon kolejki, usuń (dequeue) usuń dane z głowy kolejki. Gdy głowa jest równa ogonowi, kolejka jest pusta. Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 32
Przykład: kolejka1.c #include <stdio.h> #include <stdlib.h> struct wezelkolejki char dana; struct wezelkolejki *nastepnywsk; ; typedef struct wezelkolejki WEZELKOLEJKI; typedef WEZELKOLEJKI *WEZELKOLEJKIWSK; /* prototypy funkcji */ void drukujkolejke(wezelkolejkiwsk); int jestpusta(wezelkolejkiwsk); char usun(wezelkolejkiwsk *, WEZELKOLEJKIWSK *); void wstaw(wezelkolejkiwsk *, WEZELKOLEJKIWSK *, char); void polecenia(void); Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 33
main() WEZELKOLEJKIWSK glowawsk = NULL, ogonwsk = NULL; int wybor; char pozycja; polecenia(); printf("? "); scanf("%d", &wybor); while (wybor!= 3) switch(wybor) case 1: printf("wprowadz znak: "); scanf("\n%c", &pozycja); wstaw(&glowawsk, &ogonwsk, pozycja); drukujkolejke(glowawsk); break; Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 34
case 2: if (!jestpusta(glowawsk)) pozycja = usun(&glowawsk, &ogonwsk); printf("%c zostalo usuniete.\n", pozycja); drukujkolejke(glowawsk); break; default: printf("zly wybor.\n\n"); polecenia(); break; printf("? "); scanf("%d", &wybor); printf("koniec pracy.\n"); return 0; Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 35
void polecenia(void) printf ("Wprowadz swoj wybor: \n" " 1 aby dodac wezel do kolejki \n" " 2 aby usunac wezel z kolejki \n" " 3 aby zakonczyc \n"); Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 36
void wstaw(wezelkolejkiwsk *glowawsk, WEZELKOLEJKIWSK *ogonwsk, char wartosc) WEZELKOLEJKIWSK nowywsk; nowywsk = malloc(sizeof(wezelkolejki)); if (nowywsk!= NULL) nowywsk->dana = wartosc; nowywsk->nastepnywsk = NULL; if (jestpusta(*glowawsk)) *glowawsk = nowywsk; else (*ogonwsk)->nastepnywsk = nowywsk; *ogonwsk = nowywsk; else printf("%c nie wstawione do kolejki. Brak dostepnej pamieci.\n", wartosc); Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 37
char usun(wezelkolejkiwsk *glowawsk, WEZELKOLEJKIWSK *ogonwsk) char wartosc; WEZELKOLEJKIWSK biezacywsk; wartosc = (*glowawsk)->dana; biezacywsk = *glowawsk; *glowawsk = (*glowawsk)->nastepnywsk; if (*glowawsk == NULL) *ogonwsk = NULL; free(biezacywsk); return wartosc; Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 38
int jestpusta(wezelkolejkiwsk glowawsk) return glowawsk == NULL; void drukujkolejke(wezelkolejkiwsk biezacywsk) if (biezacywsk == NULL) printf("kolejka jest pusta.\n\n"); else printf("kolejka zawiera:\n"); while (biezacywsk!= NULL) printf("%c --> ", biezacywsk->dana); biezacywsk = biezacywsk->nastepnywsk; printf("null\n\n"); Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 39
Przykład: kolejka2.cpp #include <iostream> #include <string> using namespace std; struct kolejka char dana[10]; kolejka *ref; ; kolejka *wskaznik; kolejka *tmp; kolejka *pierwszy; //Wsk. do pierwszego wezla kolejki Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 40
void wstaw_do_kolejki(char dodaj[10]) tmp=new kolejka; strcpy(tmp->dana,dodaj); if (wskaznik==null) pierwszy=tmp; //ustawianie wsk. //do pierwszego wezla else wskaznik->ref=tmp; wskaznik=tmp; void usun_wezel(void) if (pierwszy!=null) tmp=pierwszy->ref; printf("usunieto: %s\n",pierwszy->dana); delete pierwszy; pierwszy=tmp; else printf("kolejka jest pusta\n"); Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 41
void drukuj_kolejke() printf("zawartosc kolejki:\n"); tmp=pierwszy; while (tmp!=null) cout <<tmp->dana<<"\n"; tmp=tmp->ref; void usun_wszystko(void) while (pierwszy!=null) usun_wezel(); printf("\nkolejka oczyszczona. Dowolny klawisz..."); Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 42
int main(void) char dana[10]; printf("wprowadz dana do kolejki, do 10 znakow, bez spacji):\n"); printf(" # - usun pierwszy wezel, \n" " $ - wypisz zawartosc kolejki, \n" " & - usun wszystko i zakoncz \n"); Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 43
do printf("dane: "); scanf("%s",&dana); if (strcmp(dana,"&")!=0) if (strcmp(dana,"#")==0) usun_wezel(); else if (strcmp(dana,"$")==0) drukuj_kolejke(); else wstaw_do_kolejki(dana); while (strcmp(dana,"&")!=0); usun_wszystko(); system("pause"); return 0; Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 44
Kolejka priorytetowa (j. ang.: priority queue) Przykłady: osoby uprzywilejowane w kolejce, pojazdy uprzywilejowane na skrzyżowaniach, procesy uprzywilejowane w komputerowym przetwarzaniu danych. Zasada: węzły są usuwane według ich priorytetu oraz bieżącej pozycji w kolejce. Problem: znalezienie efektywnej implementacji szybkiego wstawiania i usuwania węzłów (kryteria mogą być złożone). Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 45
Kolejka priorytetowa (j. ang.: priority queue) Definicja: Kolejka priorytetowa jest strukturą danych zawierającą węzły z kluczami, pozwalającą na przeprowadzanie operacji wstawiania nowego węzła iusuwaniawęzła o najwyższej wartości klucza. Implementacja: z wykorzystaniem podstawowych struktur danych: uporządkowanych bądź nieuporządkowanych tablic, list lub kopców (j. ang.: heap, inne nazwy: sterta, stóg). Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 46
Poznań 2009/2010 Algorytmy i struktury danych Krzysztof Nowakowski 47