1/98 Sortowanie bąbelkowe (Bubble sort) prosty i nieefektywny algorytm sortowania wielokrotnie przeglądamy listę elementów, porównując dwa sąsiadujące i zamieniając je miejscami, jeśli znajdują się w złym porządku przechodzenie powtarzamy, dopóki lista nie zostanie posortowana (i dalsze zamiany nie będą konieczne) średnia złożoność O(n 2 ) pseudokod: repeat swapped = false for i = 1 to length(a) - 1 do: if A[i-1] > A[i] then swap( A[i-1], A[i] ) swapped = true end if end for until not swapped
pierwsze przejście: 5 1 1 1 1 1 1 1 1 5 5 4 4 4 4 4 4 4 4 5 5 2 2 2 2 2 2 2 2 5 5 5 8 8 8 8 8 8 8 8 drugie przejście: 1 1 1 1 1 1 1 1 4 4 4 2 2 2 2 2 2 2 2 4 4 4 4 4 5 5 5 5 5 5 5 5 8 8 8 8 8 8 8 8 trzecie przejście: 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 4 4 4 4 4 4 4 4 5 5 5 5 5 5 5 5 8 8 8 8 8 8 8 8 2/98
3/98 Sortowanie przez wstawianie (Insertion sort) ciąg dzielimy (umownie) na część uporządkowaną (na początku pustą) oraz nieuporządkowaną pierwszy element ciągu nieuporządkowanego przenosimy na właściwe miejsce ciągu uporządkowanego (tak, aby ciąg nadal był uporządkowany) powtarzamy dla kolejnym elementów 6 5 3 1 8 7 2 4 6 5 3 1 8 7 2 4 5 6 3 1 8 7 2 4 3 5 6 1 8 7 2 4 1 3 5 6 8 7 2 4 1 3 5 6 8 7 2 4 1 3 5 6 7 8 2 4 1 2 3 5 6 7 8 4 1 2 3 4 5 6 7 8
4/98 Sortowanie przez wybieranie (Selection sort) odnajdujemy najmniejszą wartość zamieniamy ją z wartością zajmującą jej miejsce (czyli znajdującą się na pierwszej pozycji) powtarzamy dla pozostałej części ciągu 6 5 3 1 8 7 2 4 1 5 3 6 8 7 2 4 1 2 3 6 8 7 5 4 1 2 3 6 8 7 5 4 1 2 3 4 8 7 5 6 1 2 3 4 5 7 8 6 1 2 3 4 5 6 8 7 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
5/98 Sortowanie przez zliczanie (Counting sort) założenie elementy ciągu są wartościami całkowitymi z określonego przedziału dla każdej wartości zliczamy liczbę jej wystąpień w ciągu na tej podstawie określamy położenie wartości w posortowanym ciągu i umieszczamy je na pozycjach docelowych 4 3 1 5 5 4 1 5 wartość 1 2 3 4 5 wystąpienia 2 0 1 2 3 1 1 3 4 4 5 5 5
6/98 Sortowanie kubełkowe (Bucket sort) dzielimy przedział możliwych wartości na określoną liczbę podprzedziałów (kubełków) umieszczamy kolejno wartości wejściowego ciągu w odpowiednich kubełkach 3 9 29 25 3 49 9 37 21 43 29 25 21 37 49 43 0-9 10-19 20-29 30-39 40-49 sortujemy osobno każdy z niepustych kubełków 3 9 22 25 29 37 43 49 0-9 10-19 20-29 30-39 40-49 pobieramy kolejno elementy z kubełków 3 9 22 25 29 37 43 49
7/98 Sortowanie szybkie (Quicksort) odnajdujemy element rozdzielający v dzielimy ciąg na dwie części: wartości mniejsze bądź równe v oraz wartości większe bądź równe v właściwa pozycja elementu v jest pomiędzy tymi dwiema częściami powtarzamy operację dla obu tych części 6 4 8 5 9 7 2 3 1 4 5 2 3 1 6 8 9 7 4 5 2 3 1 6 8 9 7 2 3 1 4 5 6 7 8 9 2 3 1 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9
8/98 Sortowanie przez scalanie (Merge sort) algorytm sortowania oparty na strategii dziel i zwyciężaj sortowanie opiera się na połączeniu dwóch uporządkowanych połówek w jeden posortowany ciąg uporządkowane połówki uzyskujemy scalając ich uporządkowane połówki proces dzielenia tablicy kończy się, gdy zawiera ona mniej niż 2 elementy 8 2 8 6 4 3 1 5 8 2 8 6 4 3 1 5 8 2 8 6 4 3 1 5 8 2 8 6 4 3 1 5 2 8 6 8 3 4 1 5 2 6 8 8 1 3 4 5 1 2 3 4 5 6 8 8
9/98 Sortowanie przez kopcowanie (Heapsort) kopiec binarny drzewo binarne o następujących dwóch własnościach: o wartość w dowolnym jego węźle jest niemniejsza niż wartości przechowywane w każdym z jego synów (tzw. własność kopca) o wszystkie liście w drzewie leżą na co najwyżej dwóch ostatnich poziomach, a liście na ostatnim poziomie szczelnie wypełniają jego lewą część 8 6 7 4 5 3 2 1 algorytm: o ciąg zostaje przekształcony do postaci kopca o zamieniamy korzeń z ostatnim elementem kopca (nieuporządkowanej części ciągu) o przywracamy drzewu własności kopca
10/98 rysunek drzewa 6 5 3 1 8 7 2 4 6 tablica do posortowania 6 tablicowa reprezentacja drzewa budowanie drzewa
11/98 dodajemy 6 5 3 1 8 7 2 4 5 6 6 5
12/98 dodajemy 6 5 3 1 8 7 2 4 6 5 3 6 5 3
13/98 dodajemy 6 5 3 1 8 7 2 4 6 5 3 1 6 5 3 1
14/98 dodajemy 6 5 3 1 8 7 2 4 6 5 3 1 8 6 5 3 1 8
15/98 6 5 3 1 8 7 2 4 6 5 3 1 8 wymagane przywrócenie struktury kopca 6 5 3 1 8
16/98 6 5 3 1 8 7 2 4 6 8 3 1 5 6 8 3 1 5
17/98 6 5 3 1 8 7 2 4 6 8 3 1 5 6 8 3 1 5
18/98 6 5 3 1 8 7 2 4 8 6 3 1 5 8 6 3 1 5
19/98 dodajemy 6 5 3 1 8 7 2 4 8 6 3 1 5 7 8 6 3 1 5 7
20/98 6 5 3 1 8 7 2 4 8 6 3 1 5 7 8 6 3 1 5 7
21/98 6 5 3 1 8 7 2 4 8 6 7 1 5 3 8 6 7 1 5 3
22/98 dodajemy 6 5 3 1 8 7 2 4 8 6 7 1 5 3 2 8 6 7 1 5 3 2
23/98 dodajemy 6 5 3 1 8 7 2 4 8 6 7 1 5 3 2 4 8 6 7 1 5 3 2 4
24/98 6 5 3 1 8 7 2 4 8 6 7 1 5 3 2 4 8 6 7 1 5 3 2 4
25/98 6 5 3 1 8 7 2 4 8 6 7 4 5 3 2 1 8 6 7 4 5 3 2 1
26/98 sortowanie 8 6 7 4 5 3 2 1 8 6 7 4 5 3 2 1
27/98 1 usuwanie 6 7 4 5 3 2 1 6 7 4 5 3 2 8
28/98 1 6 7 przywracanie struktury kopca 4 5 3 2 1 6 7 4 5 3 2 8
29/98 7 6 1 4 5 3 2 7 6 1 4 5 3 2 8
30/98 7 6 1 4 5 3 2 7 6 1 4 5 3 2 8
31/98 7 6 3 4 5 1 2 7 6 3 4 5 1 2 8
32/98 7 6 3 4 5 1 2 7 6 3 4 5 1 2 8
33/98 2 usuwanie 6 3 4 5 1 2 6 3 4 5 1 7 8
34/98 2 6 3 przywracanie struktury kopca 4 5 1 2 6 3 4 5 1 7 8
35/98 6 2 3 4 5 1 6 2 3 4 5 1 7 8
36/98 6 2 3 4 5 1 6 2 3 4 5 1 7 8
37/98 6 5 3 4 2 1 6 5 3 4 2 1 7 8
38/98 6 usuwanie 5 3 4 2 1 6 5 3 4 2 1 7 8
39/98 1 5 3 4 2 1 5 3 4 2 6 7 8
40/98 1 5 3 przywracanie struktury kopca 4 2 1 5 3 4 2 6 7 8
41/98 5 1 3 4 2 5 1 3 4 2 6 7 8
42/98 5 1 3 4 2 5 1 3 4 2 6 7 8
43/98 5 4 3 1 2 5 4 3 1 2 6 7 8
44/98 5 usuwanie 4 3 1 2 5 4 3 1 2 6 7 8
45/98 2 4 3 1 2 4 3 1 5 6 7 8
46/98 2 4 3 przywracanie struktury kopca 1 2 4 3 1 5 6 7 8
47/98 4 2 3 1 4 2 3 1 5 6 7 8
48/98 4 usuwanie 2 3 1 4 2 3 1 5 6 7 8
49/98 1 2 3 1 2 3 4 5 6 7 8
50/98 1 2 3 przywracanie struktury kopca 1 2 3 4 5 6 7 8
51/98 3 2 1 3 2 1 4 5 6 7 8
52/98 3 usuwanie 2 1 3 2 1 4 5 6 7 8
53/98 1 2 1 2 3 4 5 6 7 8
54/98 2 1 przywracanie struktury kopca 1 2 3 4 5 6 7 8
55/98 2 1 2 1 3 4 5 6 7 8
56/98 2 usuwanie 1 2 1 3 4 5 6 7 8
57/98 1 1 2 3 4 5 6 7 8 posortowana tablica 1 2 3 4 5 6 7 8
Wyszukiwanie liniowe poszukujemy wartości x w n-elementowym ciągu w najgorszym przypadku musimy sprawdzić wszystkie jego elementy 6 3 8 2 5 7 4 2 6 3 8 2 5 7 4 2 6 3 8 2 5 7 4 2 6 3 8 2 5 7 4 2 58/98
59/98 Wyszukiwanie binarne poszukujemy wartości x w n-elementowym uporządkowanym ciągu porównujemy z elementem znajdującym się w środku dostępnego zakresu za każdym porównaniem zmniejszamy zakres o połowę (odrzucamy część, w której szukany element nie może się znaleźć) 1 2 4 5 6 8 9 4 1 2 4 5 6 8 9 4 1 2 4 5 6 8 9 4
60/98 Struktura słownikowa dynamiczna (mogąca zmieniać się w czasie) struktura danych umożliwia dokonanie takich operacji jak: o wstawienie elementu o usunięcie elementu o wyszukanie elementu o zadanych własnościach Drzewo struktura umożliwiająca przechowywanie danych zbudowanych z węzłów oraz wskaźników do potomków drzewo binarne każdy węzeł posiada dwóch potomków: lewego i prawego drzewo BST wszystkie elementy umieszczone w lewym poddrzewie są mniejsze od swego ojca, zaś w prawym większe (inaczej niż w kopcu) 4 2 8 1 3 6 9 0 7
61/98 Dodawanie elementu do drzewa: poczynając od korzenia porównujemy nowy element z węzłami jeśli jest mniejszy, poruszamy się lewo, a jeśli większy w prawo wstawiamy element w znalezione wolne miejsce
62/98 4 2 8 dodajemy5 1 3 6 9 0 7
63/98 4 2 8 dodajemy5 1 3 6 9 0 7
64/98 4 2 8 1 3 6 9 0 7 dodajemy5
65/98 4 2 8 1 3 6 9 0 5 7 dodajemy5
66/98 Wyszukiwanie elementu w drzewie: rozpoczynając od korzenia, porównujemy wartość w węźle z wartością poszukiwaną jeśli nie znaleźliśmy wartości, to szukamy jej: o w lewym poddrzewie, jeśli szukana wartość jest mniejsza od znalezionej o w prawym, jeśli jest większa
67/98 szukamy 3 4 2 8 1 3 6 9 0 5 7
68/98 4 szukamy 3 2 8 1 3 6 9 0 5 7
69/98 4 2 8 1 3 6 9 0 5 7 znaleźliśmy 3
70/98 Usuwanie elementu możliwe są trzy przypadki: usuwany węzeł nie ma potomstwa wówczas po prostu usuwamy ten element: 4 usuwamy 2 8 1 3 6 9 0 5 7 4 2 8 1 6 9 0 5 7
71/98 usuwany węzeł ma jednego potomka rodzic usuwanego elementu będzie wskazywał na jego potomka usuwamy 4 2 8 1 6 9 0 5 7 4 1 8 0 6 9 5 7
72/98 usuwany element ma dwóch potomków wówczas w miejsce usuwanego wierzchołka wstawiamy wierzchołek o najmniejszej wartości z prawego (lub największej z lewego) poddrzewa usuwamy 4 1 8 najmniejszy element prawego poddrzewa 0 6 9 5 7 5 1 8 0 6 9 7
73/98 Drzewa wyważone drzewo jest wyważone, gdy dla każdego węzła wysokość jego dwóch poddrzew różni się co najwyżej o 1 5 1 1 8 0 8 0 6 9 5 9 7 7 drzewo wyważone 6 drzewo niewyważone
74/98 drzewo AVL w drzewie AVL każdy wierzchołek (poza wartością i wskazaniami na potomków) przechowuje informację dotyczącą wyważenia: różnicę wysokości lewego i prawego poddrzewa jeśli w wyniku dodania lub usunięcia węzła ta wartość stanie się większa od 1 lub mniejsza od -1, drzewo należy zrównoważyć służy do tego mechanizm rotacji przed wstawieniem:
75/98 po wstawieniu (przypadek 1): rotacja:
76/98 po wstawieniu (przypadek 2): rotacja:
77/98 wstawianie elementu do drzewa AVL: idąc w dół szukaj miejsca na wstawienie elementu cofając się na ścieżce przeszukiwania, aktualizuj współczynnik wyważenia jeśli wynosi on -2 lub +2, wykonaj rotację powyżej nie ma już potrzeby poprawiania współczynników wyważenia przykład: 1 1 0 8 0 8 5 9 5 9 7
78/98 1 0 8 5 9 7 5 1 8 0 7 9
79/98 usuwanie elementu z drzewa AVL: idąc w dół szukaj elementu do usunięcia po usunięciu elementu cofaj się w ścieżce, aktualizując współczynnik wyważenia; jeśli wynosi on -2 lub +2, wykonaj rotację powtórz aktualizację współczynników (i ewentualne rotacje) dla węzłów powyżej Równoważenie drzewa algorytm DSW faza pierwsza obracanie drzewa w prawo (poczynając od korzenia) aż do uzyskania listy 7 2 9 1 4 5
80/98 obracanie drzewa w prawo 2 1 7 4 9 5
81/98 obracanie drzewa w prawo 1 2 7 4 9 5
82/98 obracanie drzewa w prawo 1 2 4 7 5 9
83/98 obracanie drzewa w prawo 1 2 4 5 7 9
84/98 Równoważenie drzewa algorytm DSW faza druga równoważenie; co drugi element (licząc od korzenia) obracamy w lewo, powtarzając to aż do uzyskania zrównoważonego drzewa 1 2 4 5 7 9
85/98 obracanie drzewa w lewo 2 1 4 5 7 9
86/98 obracanie drzewa w lewo 2 1 5 4 7 9
87/98 obracanie drzewa w lewo 2 1 5 4 9 7
88/98 obracanie drzewa w lewo 5 2 9 1 4 7
89/98 B-drzewo drzewo poszukiwań wyższych rzędów każdy węzeł może posiadać maksymalnie l węzłów potomnych (gdzie l to rząd drzewa) poza wskaźnikami do potomków, każdy węzeł zawiera też wartości rozdzielające zrównoważnienie zapewniane przez zmienne wypełnienie węzłów wszystkie liście na tym samym poziomie umożliwia odczyt danych porcjami
90/98 wyszukiwanie wartości jak w drzewie BST dodawanie wartości: 31 14 48 70 wstawiamy 64 8 12 19 35 37 55 61 75 99 31 14 48 70 8 12 19 35 37 55 61 64 75 99 przepełnienie
91/98 31 14 48 70 8 12 19 35 37 55 61 64 75 99 rozbicie 31 14 48 61 70 przepełnienie 8 12 19 35 37 55 64 75 99
92/98 31 14 48 61 70 8 12 19 35 37 55 64 75 99 48 przesunięcie 14 31 61 70 8 12 19 35 37 55 64 75 99
93/98 usuwanie wartości: usuwamy 8 31 14 48 70 8 19 35 37 55 61 75 99 31 14 48 70 19 35 37 55 61 75 99 niedobór
94/98 łączymy 31 14 48 70 19 35 37 55 61 75 99 niedobór 31 48 70 14 19 35 37 55 61 75 99
95/98 31 przemieszczamy 48 70 14 19 35 37 55 61 75 99 48 31 70 14 19 35 37 55 61 75 99
96/98 Drzewo trie drzewo prefiksowe w węzłach przechowywane są fragmenty kluczy (a nie całe klucze) służy do zapamiętywania zbioru słów jest stosowane do sprawdzania poprawności, dzielenia wyrazów, wyszukiwania słów o danym prefiksie sprawdzenie, czy słowo znajduje się w drzewie ma złożoność O(k), gdzie k to długość słowa cage car cat coma comb c a om dodawanie słowa: ge r t a b a c om dodajemy comet ge r t a b et
97/98 Tablica mieszająca (Hash table) tablica asocjacyjna, identyfikująca dane na podstawie klucza opiera się na zwykłej tablicy indeksowanej (szybki dostęp) funkcja mieszająca wyznacza indeks dla danego klucza funkcja mieszająca powinna być dobrana do danych
98/98 kolizja gdy funkcja mieszająca przypisze tę samą wartość indeksu dwóm kluczom (doskonała funkcja mieszająca nigdy nie spowoduje kolizji) możliwe rozwiązanie metoda łańcuchowa: indeks w tablicy odsyła nas nie do danych, ale do listy możliwych danych