Pojęcia podstawowe. Złożonośd czasowa algorytmów. Rekurencja Algorytmy i struktury danych Wykład 1. Rok akademicki: 2010/2011 Ramowy plan wykładów Pojęcie podstawowe. Poprawnośd i złożonośd algorytmów Rekurencja Algorytmy tablicowe Zbiory Tablice asocjacyjne Struktury listowe Drzewa Grafy 2 1
Literatura Cormen T., Leiserson C., Rivest R., Stein C., Wprowadzenie do algorytmów, Wydawnictwo Naukowo-Techniczne, 2004 Lafore R., Java. Algorytmy i struktury danych, Helion, 2004 Koffman E., Wolfgang P., Struktury danych i techniki obiektowe na przykładzie Javy 5.0, Helion, 2006 Wirth N., Algorytmy + struktury danych = programy, dowolne wydanie Sysło M., Algorytmy, Wydawnictwo Szkolne i Pedagogiczne, Warszawa, 1997 3 Informacje organizacyjne Wymiar godzinowy: 30 + 30 Terminy zajęd: sroda, 13.05, s. 441 Budynek BG Egzamin: pisemny (nie ma zwolnieo z egzaminu) Materiały do wykładu: http://www.uek.krakow.pl/~lulap 4 2
Algorytm sposób postępowania umożliwiający rozwiązanie zadania określonego typu podany w postaci zestawu kolejnych czynności do wykonania wykonawcą algorytmu może byd człowiek lub urządzenie (np. komputer) 5 Struktura danych Zestaw powiązanych ze sobą danych wraz z mechanizmami określającymi sposób tworzenia, likwidowania i wykorzystania zdefiniowanego zestawu jako całości oraz poszczególnych jego elementów. 6 3
Program komputerowy zrozumiały dla komputera sposób zapisu algorytmu i opisu struktur danych zapisywany przy użyciu języków programowania. 7 Ewolucja metod programowania (1) Programowanie w języku maszynowym Programista posługuje się pojęciami charakterystycznymi dla systemu komputerowego, a nie dla dziedziny zastosowao (operuje rozkazami wchodzącymi w skład listy rozkazów procesora) Rozkazy składające się na program programista zapisu w postaci binarnych kodów Programista operuje bezpośrednio na komórkach pamięci operacyjnej. Odpowiedzialny jest za określenie sposobu binarnej reprezentacji informacji. 8 4
Ewolucja metod programowania (2) Programowanie w języku symbolicznym (asemblerze) Programista posługuje się rozkazami pochodzącymi z listy rozkazów procesora (ale są one zapisywane w postaci instrukcji, a nie w postaci binarnych kodów). Języki symboliczne wprowadziły zmiany w sposobie notacji programu, ale nie spowodowały zasadniczych zmian w zestawie pojęd wykorzystywanych do opisu algorytmów. Pojawiła się możliwośd przypisywania nazw komórkom pamięci (definiowanie zmiennych) 9 Ewolucja metod programowania (3) Programowanie w językach wysokiego poziomu I generacji Pojawiła się możliwośd stosowania instrukcji: podstawienia (przypisania), warunkowej, pętli (iteracji), skoku. Przy opisie algorytmy następuje rezygnacja ze stosowania rozkazów z listy rozkazów procesora i pojawia się możliwośd stosowania pojęd o znacznie większym stopniu ogólności. Wprowadzenie mechanizmu deklarowania zmiennych Ułatwione zostało operowanie na wartościach tekstowych Pojawiła się możliwośd korzystania ze złożonych typów danych (tablice, pliki) 10 5
Ewolucja metod programowania (4) Programowanie proceduralne Możliwośd definiowania podprogramów. Zdefiniowanie nowego podprogramu pozwala na rozszerzenie zbioru instrukcji dostępnych w stosowanym języku programowania. Mechanizm parametrów zwiększył uniwersalnośd definiowanych instrukcji. Pojawiła się możliwośd definiowania danych lokalnych (dostępnych tylko w podprogramie) oraz danych globalnych (dostępnych w całym programie) 11 Ewolucja metod programowania (5) Programowanie strukturalne Zwiększenie liczby instrukcji sterujących (np.: różne postaci pętli, instrukcji warunkowych, wyboru, podstawienia) dzięki czemu można było wyeliminowad instrukcję skoku bezwarunkowego Podział programu na dwie części: opis struktur danych i opis algorytmu Zwiększenie liczby dostępnych typów danych (tablice, rekordy, zbiory, pliki), Możliwośd stosowania dynamicznych struktur danych (stos, kolejka, listy, drzewa), Możliwośd definiowania własnych struktur danych. 12 6
Ewolucja metod programowania (6) Programowanie obiektowe Równoległe definiowanie algorytmów i struktur danych i ich połączenie w jedną całośd (klasę): reprezentuje w programie fragment rzeczywistości (jego cechy, jego zachowania), pozwala programiście posługiwad się pojęciami charakterystycznymi dla dziedziny problemu (oderwad się od pojęd związanych ze sprzętem komputerowym), pozwala ukryd szczegóły implementacji klasa abstrakcyjny typ danych (ABSTRAHOWANIE - operacja myślowa polegająca na uwzględnianiu tylko wybranych cech sytuacji (przedmiotu, osoby), z pominięciem cech uznanych za nieistotne) 13 Wymagania wobec algorytmów poprawnośd algorytm generuje prawidłowe rezultaty (nie zawiera błędów), wydajnośd realizacja algorytmu wymaga użycia akceptowalnej ilości zasobów: czasu, pamięci. 14 7
Pojęcie błędu niezgodnośd z obowiązującymi regułami pisania, liczenia, wymowy itp.; odstępstwo od normy; pomyłka postępek, działanie, które przynosi komuś złe skutki; niewłaściwe posunięcie, przedsięwzięcie mylne, fałszywe mniemanie o czymś (przestarz.) Źródło: Słownik języka polskiego PWN 15 Błędy w programowaniu błędy logiczne na etapie projektowania algorytmu (środki zaradcze: stosowanie sprawdzonych algorytmów, formalne dowodzenie poprawności algorytmu, testowanie programu) błędy wykonania programu ujawniające się w trakcie realizacji algorytmu zapisanego w postaci programu (ujawniające się w postaci wyjątków) błędy syntaktyczne polegające na niezgodności tekstu programu z gramatyką języka programowania (wykrywane przez kompilator) 16 8
Złożonośd obliczeniowa Złożonośd obliczeniowa algorytmu ilośd zasobów systemu komputerowego niezbędnych do jego realizacji. Zasoby systemu komputerowego niezbędne do realizacji algorytmu: czas pracy procesora (złożonośd czasowa algorytmu), pamięd operacyjna (złożonośd pamięciowa algorytmu). Złożonośd obliczeniowa jest uzależniona od wielkości zadania. 17 Sortowania przez wybieranie (1) import java.io.*; public class SortowaniePrzezWybieranie { static void sortuj(int [] liczby) { int k, pomoc; for (int i = 0; i < liczby.length - 1; i++) { k = i; for (int j = i; j < liczby.length; j++) if (liczby[k] > liczby[j]) k = j; pomoc = liczby[i]; liczby[i] = liczby[k]; liczby[k] = pomoc; 18 9
Sortowania przez wybieranie (2) static int czytajliczbe() throws IOException { BufferedReader klaw = new BufferedReader (new InputStreamReader (System.in)); return Integer.parseInt(klaw.readLine()); static void drukujwektor(int [] tab) { for (int i = 0; i < tab.length; i++) System.out.print(tab[i] + " "); System.out.print("\n"); 19 Sortowania przez wybieranie (3) public static void main(string [] args) throws IOException { System.out.print("Liczba elementow w wektorze: "); int n = czytajliczbe(); int [] wektor = new int[n]; for (int i = 0; i < wektor.length; i++) wektor[i] = (int) (100 * Math.random()); long czas1, czas2; czas1 = System.currentTimeMillis(); // czas w milisekundach, jaki upłynął od // 1 stycznia 1970 roku, godz. 0:00 sortuj(wektor); czas2 = System.currentTimeMillis(); System.out.println("Czas realizacji obliczen: " + (czas2 - czas1)); 20 10
Sortowania przez wybieranie (4) Rezultat działania programu: Liczba elementow w wektorze: 10000 Czas realizacji obliczen: 250 21 Czas realizacji algorytmu (1) 22 11
Czas realizacji algorytmu (2) Czas (milisekundy) 120000 100000 80000 60000 40000 20000 0 0 50000 100000 150000 200000 250000 y = 0,000002 n 2 0,0094 n + 286,41 23 Oszacowanie czasu realizacji algorytmu (1) 24 12
Oszacowanie czasu realizacji algorytmu (2) Analiza powyższych danych pozwala stwierdzid, że czas obliczeo uzależniony jest przede wszystkim od składnika: 0,000002 n 2 Składnik ten nazywany jest składnikiem dominującym. Po pominięciu stałych współczynników można stwierdzid, że zależnośd pomiędzy czasem wykonania a wielkością zadania ma charakter funkcji kwadratowej. Kwadratowy charakter zależności uwidacznia się w coraz większym stopniu wraz ze wzrostem wielkości zadania. 25 Cechy empirycznego określania złożoności Zalety: otrzymane czasy obliczeo są proste w interpretacji Wady: koniecznośd wielokrotnego uruchamiania programu (dla złożonych algorytmów może to byd bardzo czasochłonne), uzyskane wyniki dotyczą zastosowanego w obliczeniach zestawu danych (trudno jest określid czas realizacji dla przypadku najlepszego, najgorszego oraz przeciętnego ), wyniki dotyczą zwykle stosunkowo niewielkich zbiorów danych nie wiadomo, czy dla zbiorów o większym rozmiarze charakter zależności się nie zmieni, czas jest uzależniony od szybkości i architektury komputera, języka programowanie, techniki translacji, systemu operacyjnego trudna porównywalnośd wyników z uwagi na wielozadaniowy charakter systemów operacyjnych trudno jest określid, jaka częśd czasu była rzeczywiście przeznaczona na realizację analizowanego programu. 26 13
Bezpośrednia analiza algorytmów Analiza dotyczy: charakteru zależności (np. zależnośd liniowa lub kwadratowa), a nie jej dokładnej postaci (wzór funkcji) uwzględniany jest element dominujący, pomijane są współczynniki stałe górnego i dolnego ograniczenia czasu realizacji algorytmu (a nie czasu realizacji algorytmu) górne ograniczenie czas realizacji algorytmu jest nie większy niż... (ale może byd krótszy) przypadek pesymistyczny, dolne ograniczenie czas realizacji algorytmu jest nie mniejszy niż... (ale może byd dłuższy) przypadek optymistyczny, zachowania się algorytmu dla zbiorów danych o dużej wielkości (czyli dla wszystkich n większych od pewnej wartości n 0 ) 27 Górne ograniczenie czasu realizacji algorytmu (1) f(n) czas realizacji algorytmu (zależny od n) f(n) zależy od wielu czynników i podanie dokładnego charakteru zależności jest trudne łatwiej jest zdefiniowad ograniczenie górne dla f(n). c g(n) f(n) n 28 14
Górne ograniczenie czasu realizacji algorytmu (2) Czas realizacji algorytmu jest rzędu co najwyżej g(n), jeśli istnieją stała rzeczywista c > 0 i stała naturalna n 0 takie, że nierównośd f(n) c g(n) zachodzi dla każdego n n 0. Zbiór wszystkich funkcji f(n) spełniających powyższe ograniczenie określany jest jako O(g(n)). O(g(n)) = {f(n): istnieją dodatnie stałe c oraz n 0 takie, że 0 f(n) c g(n) dla wszystkich n n 0 29 Górne ograniczenie czasu realizacji algorytmu (3) Stwierdzenie: czas realizacji algorytmu wynosi O(g(n)) lub czas realizacji algorytmu jest rzędu co najwyżej g(n) lub algorytm jest klasy O(g(n)) oznacza: że istnieje taka stała c, że dla n n 0 czas realizacji algorytmu wynosi co najwyżej c g(n). 30 15
Dolne ograniczenie czasu realizacji algorytmu (4) Czas realizacji algorytmu jest rzędu co najmniej g(n), jeśli istnieją stała rzeczywista c > 0 i stała naturalna n 0 takie, że nierównośd f(n) c g(n) zachodzi dla każdego n n 0. Zbiór wszystkich funkcji spełniających to ograniczenie określany jest jako Ω(g(n)) Ω(g(n)) = {f(n): istnieją dodatnie stałe c i n 0 takie, że 0 cg(n) f(n) dla wszystkich n n 0 f(n) c g(n) n 31 Dolne i górne ograniczenie czasu realizacji algorytmu (1) Czas realizacji algorytmu jest dokładnie rzędu g(n) jeśli istnieją stała rzeczywista c 1 > 0, c 2 > 0 i stała naturalna n 0 takie, że nierównośd c 1 g(n) f(n) c 2 g(n) zachodzi dla każdego n n 0. c 2 g(n) f(n) c 1 g(n) n 32 16
Dolne i górne ograniczenie czasu realizacji algorytmu (2) Zbiór wszystkich funkcji spełniających to ograniczenie określany jest jako Θ(g(n)) Θ(g(n)) = {f(n); istnieją dodatnie stałe c 1, c 2 i n 0 takie, że 0 c 1 g(n) f(n) c 2 g(n) dla wszystkich n n 0 33 Średnia złożonośd obliczeniowa Średnia złożonośd czasowa uwzględnia prawdopodobieostwa pojawienia się każdego możliwego zestawu danych wejściowych Z i (n) i-ty możliwy zestaw danych n-elementowy p i prawdopodobieostwo wystąpienia i-tego zestawu T i (n) złożonośd czasowa algorytmu dla i-tego zestawu danych Średnia złożonośd czasowa algorytmu dana jest formułą: T śr n i p T i i n 34 17
Złożonośd obliczenia sortowania przez wybieranie (1) static void sortuj(int [] liczby) { int k, pomoc; for (int i = 0; i < liczby.length - 1; i++) { //koszt K1 k = i; for (int j = i; j < liczby.length; j++) //koszt K2 if (liczby[k] > liczby[j]) k = j; //koszt K3 pomoc = liczby[i]; liczby[i] = liczby[k]; liczby[k] = pomoc; 35 Złożonośd obliczenia sortowania przez wybieranie (2) for (int i = 0; i < n - 1; i++) { K1 for (int j = i; j < n; j++) { K2 K3 36 18
Złożonośd obliczenia sortowania przez wybieranie (3) for (int i = 0; i < n - 1; i++) { K1 (n 1) * K2 K3 37 Złożonośd obliczenia sortowania przez wybieranie (4) (n 1) * K1 + (n 1) [n * K2 + (n-1) * K2 +... + 2 * K2] + (n 1) * K3 = = n * K1 K1 + *½ * (2 + n) * (n 1) * K2] + n * K3 K3 = = n * K1 K1 + n * K2 K2 + ½ * n 2 * K2 ½ * n * K2 + n * K3 K3 = = ½ * K2 * n 2 + (K1 + ½ * K2 + K3) * n (K1 + K2 + K3) = O(n 2 ) 38 19
Rodzaje złożoności (1) Złożoność logarytmiczna log n W każdym kroku algorytmu zadanie o rozmiarze n jest sprowadzane do zadania o rozmiarze n / 2 Przykład: algorytm wyszukiwania binarnego jest klasy O(log n) Przykładowa realizacja wyszukiwania binarnego: Mamy odszukad wartośd 11 w ciągu liczb: 1, 2, 7, 9, 9, 11, 12, 15, 22, 34, 52, 67, 87, 90, 99 1, 2, 7, 9, 9, 11, 12 9, 11, 12 39 Rodzaje złożoności (2) Złożoność liniowa n gdy dla każdego elementu pochodzącego z n elementowego zbioru danych wykonywana jest stała liczba operacji Przykłady: wyszukiwanie sekwencyjne sumowanie liczb w wektorze wyznaczanie minimum, maksimum 40 20
Rodzaje złożoności (3) złożoność liniowo logarytmiczna n log n gdy w każdym kroku zadanie o rozmiarze n jest sprowadzane do dwóch zadao o rozmiarze n/2, a uzyskane wyniki są ponownie scalane Przykład: sortowanie przez łączenie jest klasy O(n log n) sortowanie szybkie jest klasy O(n 2 ), ale przeciętny czas realizacji algorytmu jest rzędu n log n 41 Rodzaje złożoności (4) złożoność kwadratowa n 2 gdy dla każdej pary elementów realizowana jest pewna, stała liczba operacji (zwykle algorytmy takie są zapisywane za pomocą dwóch zagnieżdżonych pętli for) Przykłady: proste metody sortowania (przez wstawianie, wybieranie, bąbelkowe) są klasy O(n 2 ), również średni czas realizacji tych metod jest rzędu O(n 2 ) 42 21
Rodzaje złożoności (5) złożoność wielomianowa stopnia wyższego niż dwa (n 3, n 4,...) Przykład: mnożenie macierzy w sposób tradycyjny jest algorytmem klasy O(n 3 ) 43 Rodzaje złożoności (6) Złożoność wykładnicza postaci 2 n gdy realizowanych jest n kroków, a liczba operacji w każdym z nich wzrasta w sposób geometryczny Przykład: wieże Hanoi 44 22
Rodzaje złożoności (7) Złożoność wykładnicza typu n! gdy pewna, stała liczba operacji realizowana jest dla każdej permutacji n elementów Przykład: Tworzenie magicznych kwadratów z n elementów (pierwiastek z n musi byd wartością całkowitą) Algorytm postępowania: tworzymy kolejną permutację, wpisujemy do kwadratu i sprawdzamy, czy spełnia konieczne warunki. 45 Rodzaje złożoności (8) 46 23
Rekurencja Rekurencyjny sposób zapisu kodu programu - z poziomu podprogramu wywoływany jest ten sam podprogram. 47 Przykład (1) public class Rekurencja01 { static void f() { System.out.println("Poczatek"); f(); System.out.println("Koniec"); public static void main(string [] args) { f(); 48 24
Przykład (2) main() { f() Początek f(x) Koniec Początek f(x) Koniec Początek f(x) Koniec Początek f(x) Koniec i.t.d. 49 Przykład (3) Efekt uruchomienia programu: Poczatek Poczatek Poczatek... Poczatek Exception in thread "main" java.lang.stackoverflowerror 50 25
Warunek stopu Wywołania rekurencyjne muszą się zakooczyd (w podprogramie musi zostad zdefiniowany warunek zatrzymania się algorytmu /warunek stopu/). 51 Przykład (1) public class Rekurencja02 { static int licznik = 0; static void f() { licznik++; System.out.println("Poczatek"); if (licznik <=5) f(); System.out.println("Koniec"); public static void main(string [] args) { f(); 52 26
Przykład (2) main() { f() licznik = 1 Początek f(x) Koniec licznik = 2 Początek f(x) Koniec licznik = 3 Początek f(x) Koniec licznik = 4 Początek f(x) Koniec licznik = 5 Początek f(x) Koniec licznik = 6 Początek Koniec 53 Przykład (3) Efekt uruchomienia programu: Poczatek Poczatek Poczatek Poczatek Poczatek Poczatek Koniec Koniec Koniec Koniec Koniec Koniec 54 27
Rekurencyjne obliczanie silni (1) public class Rekurencja03 { static int silnia(int n) { int pomoc; System.out.println("Wywolanie: silnia(" + n + ")"); if ((n == 0) (n == 1)) pomoc = 1; else pomoc = n * silnia(n-1); System.out.println("Zwrocenie wyniku: " + n + "! = " + pomoc); return pomoc; public static void main(string [] args) { System.out.println("4! = " + silnia(4)); 55 Rekurencyjne obliczanie silni (2) 56 28
Rekurencja może byd kosztowna... public class Rekurencja04 { static int licznik = 0; static int fib(int n) //obliczanie n-tej liczby Fibonacciego { licznik++; if (n == 0) return 0; else if (n == 1) return 1; else return fib(n-1) + fib(n-2); public static void main(string [] args) { System.out.println("5-ta liczba Fibonacciego to: " + fib(5)); System.out.println("Liczba wywolan funkcji:" + licznik); 57 Efekt działania: 5-ta liczba Fibonacciego to: 5 Liczba wywolan funkcji: 15 58 29
Sposób wyznaczania liczb Fibonacciego Jeśli istnieje oczywiste rozwiązanie iteracyjne, to należy je wybrad. 59 Sterowanie kolejnością wykonywania działao (1) public class Rekurencja05 { static void sekwencja(int n) { System.out.print(n + " "); if (n > 0) sekwencja(n-1); public static void main(string [] args) { sekwencja(5); System.out.println(); Efekt działania programu: 5 4 3 2 1 0 60 30
Sterowanie kolejnością wykonywania działao (2) public class Rekurencja06 { static void sekwencja(int n) { if (n > 0) sekwencja(n-1); System.out.print(n + " "); public static void main(string [] args) { sekwencja(5); System.out.println(); Efekt działania programu 0 1 2 3 4 5 61 Wieże Hanoi public class Rekurencja08 { static void przesun(int ile, char wiezazrodlowa, char wiezadocelowa, char wiezapomocnicza) { if (ile == 1) System.out.println(wiezaZrodlowa + " => " + wiezadocelowa); else { przesun(ile-1,wiezazrodlowa,wiezapomocnicza, wiezadocelowa); System.out.println(wiezaZrodlowa + " => " + wiezadocelowa); przesun(ile-1,wiezapomocnicza,wiezadocelowa, wiezazrodlowa); 62 31
Złożonośd algorytmu: Wieże Hanoi (1) Analizowana jest liczba przesunięd potrzebna do rozwiązania zadania z n krążkami (liczbę przesunięd oznaczymy przez P(n)) gdy n = 1 to P(1) = 1 gdy n > 1 to P(n) = 2 * P(n 1) + 1 63 Złożonośd algorytmu: Wieże Hanoi (2) Poziom 0 P(n) Liczba przesunięć 1 P(n-1) 1 P(n-1) 1 2 P(n-2) 1 P(n-2) P(n-2) 1 P(n-2) 2 3 P(n-3) 1 P(n-3) P(n-3) 1 P(n-3) P(n-3) 1 P(n-3) P(n-3) 1 P(n-3) 4 64 32
Złożonośd algorytmu: Wieże Hanoi (3) P(n) = P1 + P2 + P3 +... + Pn = 2 n 1 W powyższym wzorze zastosowany został wzór na sumę n pierwszych elementów ciągu geometrycznego (o elementach b 1, b 2,..., bn i ilorazie q) S n = b 1 * (q n 1) / (q 1) 65 Inwersja elementów w wektorze (1) public class Rekurencja07 { static void wyswietlwektor(int [] w) { for(int i = 0; i < w.length; i++) System.out.print(w[i] + " "); System.out.println(); 66 33
Inwersja elementów w wektorze (2) static void inwersja(int poczatek, int koniec, int [] w) { if (poczatek < koniec) { int pomoc = w[poczatek]; w[poczatek] = w[koniec]; w[koniec] = pomoc; inwersja(poczatek+1,koniec-1,w); 67 Inwersja elementów w wektorze (3) public static void main(string [] args) { int [] tab = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11; wyswietlwektor(tab); inwersja(0,tab.length-1,tab); wyswietlwektor(tab); Efekt działania programu: 1 2 3 4 5 6 7 8 9 10 11 11 10 9 8 7 6 5 4 3 2 1 68 34
Sortowanie szybkie (1) Hoare, 1960 void quicksort(int tab[], int first, int last) wybierz jedną z wartości znajdujących się w wektorze (w poniższym algorytmie wybierana jest wartośd znajdująca się na pozycji o numerze first) dokonaj przemieszczenia elementów w wektorze, tak aby uzyskad: elementy < x x elementy >= x za pomocą tej samej procedury uporządkuj częśd wektora znajdującą się na lewo od wartości x oraz częśd znajdującą się na prawo od wartości x. średnia złożonośd obliczeniowa: O(n * log(n)) pesymistyczna złożonośd obliczeniowa O(n 2 ) 69 Sortowanie szybkie (2) public class QuickSort { public static void swap (int tab[], int x, int y) { int temp = tab[x]; tab[x] = tab[y]; tab[y] = temp; 70 35
Sortowanie szybkie (3) public static int partition(int tab[], int first, int last) { int pivot = tab[first]; int up = first; int down = last; do { while ((up < last) && (pivot >= tab[up])) up++; while (pivot < tab[down]) down--; if (up < down) swap(tab,up,down); while (up < down); swap(tab,first,down); return down; 71 Sortowanie szybkie (4) public static void quicksort(int tab[], int first, int last) { if (first >= last) return; int pivot = partition(tab, first, last); quicksort(tab, first, pivot-1); quicksort(tab, pivot+1, last); 72 36
Sortowanie szybkie (5) public static void main(string argv[]) { int n = 10; int tab[] = new int[n]; for (int i=0 ; i < n; i++) tab[i] = (int) (100 * Math.random()); quicksort(tab, 0, n-1); for (int i=0 ; i < n; i++) System.out.print(tab[i] + " "); System.out.println(); 73 Sortowanie przez łączenie Mergesort (1) sort(int poczatek, int koniec, int [] w), podziel wektory na dwie połowy, posortuj każdą z nich (za pomocą tej samej metody, o ile ich długośd > 1), połącz posortowane części w całośd, złożonośd obliczeniowa: O(n * log(n)). 74 37
Sortowanie przez łączenie Mergesort (2) public class MergeSort { static void wyswietlwektor(int [] w) { for(int i = 0; i < w.length; i++) System.out.print(w[i] + " "); System.out.println(); 75 Sortowanie przez łączenie Mergesort (3) static void sort(int poczatek, int koniec, int [] w) { if (poczatek >= koniec) return; int srodek = (poczatek + koniec) / 2; sort(poczatek, srodek, w); sort(srodek+1, koniec, w); scal(poczatek, srodek, koniec, w); 76 38
Sortowanie przez łączenie Mergesort (3) static void scal(int poczatek, int srodek, int koniec, int [] w) { int pocz1 = poczatek; int kon1 = srodek; int pocz2 = srodek + 1; int kon2 = koniec; while ((pocz1 <= kon1) && (pocz2 <= kon2)) { if (w[pocz1] < w[pocz2]) pocz1++; else { int pomoc = w[pocz2]; for (int i = pocz2-1; i >= pocz1; i--) w[i+1] = w[i]; w[pocz1] = pomoc; pocz1++; kon1++; pocz2++; 77 Sortowanie przez łączenie Mergesort (4) public static void main(string [] args) { int [] tab = {1, 5, 3, 7, 7, 9, 2, 3, 2, 2, 3; wyswietlwektor(tab); sort(0,tab.length-1,tab); wyswietlwektor(tab); Wynik działania programu 1 5 3 7 7 9 2 3 2 2 3 1 2 2 2 3 3 3 5 7 7 9 78 39