Pobierz Notatki informatyka od wielomianów - Notatki - Informatyka - Część 2 i więcej Notatki w PDF z Informatyka tylko na Docsity! Przykład: Pojedynczy przebieg – porównujemy parami od dołu: 1 2 44 44 44 44 44 44 12 55 55 55 55 55 12 44 12 12 12 12 12 55 55 42 42 42 18 18 18 18 94 94 18 42 42 42 42 18 18 94 94 94 94 94 67 67 67 67 67 67 67 Sortowanie bąbelkowe Przykład: 0 1 2 3 4 5 6 7 44 06 06 06 06 06 06 06 55 44 12 12 12 12 12 12 12 55 44 18 18 18 18 18 42 12 55 44 42 42 42 42 94 42 18 55 44 44 44 44 18 94 42 42 55 55 55 55 06 18 94 67 67 67 67 67 67 67 67 94 94 94 94 94 Złożoność czasowa O(n2). Jeśli w danym przebiegu nie dokonano żadnej zamiany, to można kończyć. Czyli w najlepszym przypadku (wartości posortowane na wejściu) mamy złożoność O(n). Sortowanie szybkie (ang. quicksort) ⋆ Typowe podejście typu dziel i zwyciężaj. ⋆ Dążymy do podziału na dwie części takie, że każdy element pierwszej części jest nie większy niż każdy element drugiej części. ⋆ Wybieramy wartość graniczną (między dwiema częściami) i szukamy od obu stron wartości, które mogłyby być po drugiej stronie ◮ kiedy znajdziemy z obu stron kandydatów do przeniesienia na drugą stronę zamieniamy ich miejscami i kontynuujemy poszukiwania. ◮ miejsce, w którym poszukiwania z obu ston „spotkają się”, to miejsce podziału ⋆ Dokonujemy podziału na dwie części i każdą sortujemy tym samym algorytmem (rekurencja!). ⋆ Jeśli do posortowania jest tylko jeden element (lub zero), to nic nie trzeba robić. Sortowanie szybkie Przykład: docsity.com 0 44 55 12 42 94 18 06 67 1 06 18 12 42 94 55 44 67 2 06 12 18 42 44 55 94 67 3 06 12 18 42 44 55 67 94 ⋆ Średnia złożoność czasowa O(nlogn). ⋆ Złożoność w najgorszym przypadku O(n2) (gdy z jednej strony podziału zawsze zostaje tylko jeden element). ⋆ Wybór wartości podziału – różne warianty, różne efekty ◮ losowo – kiepsko, bo można w ogóle nie podzielić tablicy, ◮ środek zakresu kluczy z tablicy, ◮ pierwszy/ostatni/środkowy element z tablicy. Sortowanie przez łączenie (scalanie, ang. mergesort ) Idea: Dzielimy tablicę na dwie części, sortujemy każdą z osobna a potem łączymy dwie uporządkowane tablice w jedną. Przykład: 0 44 55 12 42 94 18 06 67 1 44 55 12 42 94 18 06 67 2 44 55 12 42 94 18 06 67 3 44 55 12 42 94 18 06 67 4 44 55 12 42 18 94 06 67 5 12 42 44 55 06 18 67 94 6 06 12 18 42 44 55 67 94 Algorytm łączenia dwóch posortowanych tablic A B 12 42 44 55 06 18 67 94 C 06 12 18 42 44 55 67 94 Idea: Zaczynamy od początku posortowanych tablic i przesuwamy się do końca przepisując do docelowej tablicy dane o niższej (lub równej) wartości klucza. Uwagi: ⋆ Żeby wyznaczyć wartość minimalną wystarczy sprawdzić minimalne (pierwsze) wartości łączonych tablic. ⋆ Po przepisaniu wartości z jednej z tablic następna wartość jako minimalna z pozostałych jest kandydatem do kolejnego miejsca. docsity.com 10 { zliczamy wysta˛pienia } 11 for i := 1 to n do 12 begin 13 j := Klucz(A[i]); 14 C[j] := C[j] + 1; 15 end; 16 { liczymy indeksy ko´ncowe grup } 17 for i := 2 to k do 18 C[i] := C[i] + C[i−1]; 19 { przepisujemy od ko´nca z tablicy A do tablicy B } 20 for i := n downto 1 do 21 begin 22 j := Klucz(A[i]); 23 B[C[j]] := A[i]; 24 C[j] := C[j] − 1; 25 end; 26 SortujPrzezZliczanie := B; 27 end Struktury danych ⋆ Algorytmy + struktury danych = programy. ⋆ Struktury statyczne mają stały rozmiar (zajmują stały obszar pamięci) przez cały czas pracy. ◮ tablice – kolekcje elementów tego samego typu z dostępem swobodnym Deklaracja w Pascalu: C : array[1..n] of integer; Dostęp do elementów: C[i] ◮ rekordy (struktury) – grupują nazwane elementy różnych typów Przykład w Pascalu: 1 type Osoba = record 2 Imie : string; 3 Nazwisko : string; 4 DataUr : Data; 5 RokUkonczenia : integer; 6 end; Korzystanie: 1 var ja : Osoba; 2 begin 3 ja.Imie := ’Krzysztof’; 4 ja.DataUr.Dzien := 7; 5 ... 6 end; ⋆ Struktury dynamiczne – zmienna „objętość” danych w trakcie pracy. Pliki Pliki lub strumienie (ang. file, stream) to struktury o dostępie sekwencyjnym a nie swobodnym (jak np. tablice) ⋆ różnica jak pomiędzy zapisem na taśmach a zapisem na dyskach, ⋆ w danej chwili dostęp tylko do jednego miejsca, docsity.com ⋆ zmiana bieżącego elementu z pierwszego na ostatni wymaga przejścia przez wszystkie elementy pliku. Specyfika struktury danych narzuca odpowiednie rozwiązania algorytmiczne i odwrotnie: dla sprawnego wykonania stosownych algorytmów należy dysponować odpowiednimi strukturami danych. Dynamiczne kolekcje Przeróżne kolekcje na różne okoliczności - warto znać ich specyfikę, by trafnie dobierać struktury danych do rozwiązywanych problemów. Najważniejsze funkcje kolekcji: wstawianie (dodawanie), usuwanie, wyszukiwanie. Kolekcje: ⋆ kolejki (FIFO - first-in-first-out) ⋆ stosy (LIFO - last-in-first-out) ⋆ listy ◮ jednokierunkowe i dwukierunkowe ◮ cykliczne ⋆ drzewa ◮ binarne i niebinarne (wielokierunkowe) ◮ zbalansowane (wyważone, AVT), dokładnie wyważone ◮ czerwono-czarne ⋆ grafy Specyfika kolekcji, złożoności operacji Dla sprawnej obsługi kolekcji, zwykle z każdym elementem pamiętamy wskaźnik do następnego/poprzedniego elementu. ⋆ dodawanie i usuwanie w O(1), ⋆ wyszukiwanie w zasadzie nie stosowane, ale jeśli trzeba to O(n). Operacje na kolejkach i stosach Wstawienie obiektu o do kolejki 1 nowy.obiekt := o; 2 nowy.nast ˛epny := nil; 3 koniec.nast ˛epny := nowy; 4 koniec := nowy; Odłożenie obiektu o na stos 1 nowy.obiekt := o; 2 nowy.nast ˛epny := wierzchołek; 3 wierzchołek := nowy; Pobranie obiektu z kolejki 1 pobrany := pocza˛tek.obiekt; 2 pocza˛tek := pocza˛tek.naste˛pny; Pobranie obiektu ze stosu 1 pobrany := wierzchołek.obiekt; 2 wierzchołek := wierzchołek.nast ˛epny; Wyszukiwanie w kolejkach i stosach (i listach jednokierunkowych) jest jak poruszanie się po pomieszczeniach muzeum zgodnie z określonym kierunkiem docsity.com zwiedzania. Żeby wrócić po poprzedniego pomieszczenia, trzeba dojść do końca i zacząć od nowa. Listy jednokierunkowe Listy jednokierunkowe mają strukturę wewnętrzną taką jak kolejki (i stosy), ale z założenia pozwalają na dodatkowe operacje. Przede wszystkim: ⋆ dodawanie za wskazanym elementem, ⋆ usuwanie wybranego elementu. Dodanie elementu za wskazanym 1 nowy.nast ˛epny := wskazany.nast ˛epny; 2 wskazany.nast ˛epny := nowy; Dodanie elementu przed wskazanym kosztuje O(n) (za dużo, by używać), bo najpierw trzeba znaleźć element poprzedzający. Jeśli wstawiamy przed pierwszy, to trzeba również zweryfikować wskaźnik początku listy. Usunięcie elementu wymaga wskazania elementu poprzedniego w stosunku do usuwanego 1 usuwany := wskazany.nast ˛epny; 2 wskazany.nast ˛epny := usuwany.nast ˛epny; Listy dwukierunkowe Dodanie o za wskazanym elementem 1 nowy.obiekt := o; 2 nowy.poprzedni := wskazany; 3 nowy.nast ˛epny := wskazany.nast ˛epny; 4 wskazany.nast ˛epny := nowy; 5 nowy.nast ˛epny.poprzedni := nowy; Usunięcie elementu e 1 if e.poprzedni != nil 2 then e.poprzedni.nast ˛epny := e.nast ˛epny; 3 else pocza˛tek := e.naste˛pny; 4 if e.nast ˛epny != nil 5 then e.nast ˛epny.poprzedni := e.poprzedni; 6 else koniec := e.poprzedni; ⋆ dodawanie i usuwanie w O(1), ⋆ wyszukiwanie w O(n) - nie po to ta struktura. Drzewa Podstawowe definicje/założenia: ⋆ Drzewa to rekurencyjne kolekcje (podobnie jak kolejki, stosy czy listy), składające się z węzłów etykietowanych kolekcjonowanymi obiektami. ⋆ Drzewo jest puste bądź składa się z korzenia (węzeł główny) i kolekcji jego poddrzew. ⋆ Drzewa binarne to takie, w których każdy węzeł ma co najwyżej dwa podwęzły (lewy, prawy) a dokładniej poddrzewa. ⋆ Drzewa uporządkowane (inaczej niezbyt użyteczne): obiekt w danym węźle ma klucz nie mniejszy niż jakikolwiek węzeł jego lewego poddrzewa i nie większy niż jakikolwiek z prawego poddrzewa. ⋆ Drzewo jest dokładnie wyważone wtw, gdy dla każdego węzła, liczby węzłów w docsity.com