• Nie Znaleziono Wyników

opisowe i graficzne przedstawianie algorytmów oraz z przykładami algorytmów rozwiązywania typowych zadań numerycznych i logicznych.

N/A
N/A
Protected

Academic year: 2021

Share "opisowe i graficzne przedstawianie algorytmów oraz z przykładami algorytmów rozwiązywania typowych zadań numerycznych i logicznych."

Copied!
23
0
0

Pełen tekst

(1)

Cel i zakres kursu

Celem kursu jest poznanie metod i technik formułowania problemów i ich rozwiązań w postaci algorytmicznej. Słuchacze zapoznają się z podstawowymi pojęciami z zakresu algorytmiki takimi jak: podstawowe struktury danych,

opisowe i graficzne przedstawianie algorytmów oraz z przykładami algorytmów rozwiązywania typowych zadań numerycznych i logicznych.

Efekty kształcenia - wiedza Student po zakończeniu kursu:

- jest świadomy ograniczeń technik algorytmicznych stosowanych w zadaniach technicznych i technologicznych,

- potrafi wyjaśnić zasadę działania algorytmów wstawiania, usuwania i wyszukiwania elementów w szerokiej klasie dynamicznych struktur danych, takich jak listy, drzewa binarne, B-drzewa czy kolejki priorytetowe,

- zna podstawowe algorytmy rozwiązujące wybrane zadania algorytmiczne (np.

sortowanie, wyszukiwania wzorca w tekście, podstawowe algorytmy grafowe i

teorioliczbowe itp.)

(2)

Efekty kształcenia - umiejętności Student po zakończeniu kursu:

- potrafi interpretować schematy blokowe algorytmów oraz opracować je dla prostych zadań algorytmicznych,

- potrafi zaproponować właściwie dobraną technikę algorytmiczną do konkretnego zadania algorytmicznego (np. sortowania, wyszukiwania wzorca w tekście, itp.),

- potrafi zaproponować właściwie dobraną strukturę danych w procesie implementacji zadanego algorytmu.

Literatura podstawowa

Wróblewski P.: Algorytmy, struktury danych i języki programowania, Helion, Gliwice, 2015 Aho A. V., Hopcroft J. E., Ullman J.D.: Algorytmy i struktury danych, Helion, Gliwice, 2003.

Sedgewick R., Wayne K., Algorytmy. Wyd. IV, Helion, Gliwice 2017

Literatura uzupełniająca

Sysło M.M., Algorytmy. Wydawnictwa Szkolne i Pedagogiczne, Warszawa 1997

(3)

Wykład 1

1. Algorytm i jego własności, pojęcie problemu algorytmicznego i algorytmu, własności algorytmów, sposoby zapisu algorytmów

2. Podstawowe struktury danych

3. Złożoność algorytmów

(4)

Wg M.M.Sysły "Algorytm jest przepisem opisującym krok po kroku rozwiązanie problemu lub osiągnięcie jakiegoś celu".

Inna, klasyczna definicja algorytmu powiada, że jest to sposób rozwiązania pewnej klasy zadań.

Słowo algorytm - od fragmentu nazwiska Muhammad ibn Musa al-Chorezmi, matematyka i astronoma arabskiego (VIII/IX wiek). Był on prekursorem metod obliczeniowych w matematyce, a także twórcą pojęcia algebra.

Za prekursorkę algorytmów "komputerowych" uważa się Adę Augustę (stąd też nazwa jednego ze znanych języków programowania ADA) hrabinę Lovelace

(1815-1852), córkę Byrona.

Algorytmy przedstawia się w postaci:

- Opisu słownego

(5)

(1.1)

  x x x

f 

Przykład zadania: Obliczyć wartość funkcji

dla dowolnego, rzeczywistego x

Specyfikacja tego zadania ma postać:

Dane: Dowolna liczba rzeczywista x.

Wynik: Wartość funkcji podanej powyższym wzorem , jeżeli x jest różne od 0 oraz 0 – w przeciwnym przypadku.

 

 

 

0 x dla 1

0 x dla 0

0 x dla 1

x f

Lista kroków ma postać:

Dane: Dowolna liczba rzeczywista x.

Wynik: Wartość funkcji f(x) określona wzorem (1.2) Krok 1:Wczytaj wartość danej x.

Krok 2: Jeśli x > 0, to f(x) = 1. Zakończ Krok 3: Jeśli x = 0, to f(x) = 0. Zakończ Krok 4: {Przypadek x < 0} f(x) = -1. Zakończ

(1.2)

(6)
(7)
(8)

Metody konstrukcji algorytmów

Budowa algorytmu - proces twórczy nie podlega z góry ustalonym regułom.

Istnieją pewne ogólne metody, które można w określonych sytuacjach zastosować.

Najczęściej spotykane to metody:

Dziel i zwyciężaj– Problem rozmiaru n (o n danych) zostaje podzielony na kilka mniejszych podproblemów, w taki sposób, że z ich rozwiązań wynika rozwiązanie zasadniczego problemu. Naturalną konstrukcją algorytmiczną i programistyczną jest w tym wypadku rekurencja (rekursja).

Przykład - zadanie o tzw. wieżach z Hanoi.

Programowanie dynamiczne– "ulepszenie" metody dziel i zwyciężaj , kiedy wymaga ona wielokrotnego rozwiązywania tych samych problemów. Aby uniknąć powtarzania wyliczania tych samych wartości, zaczynamy proces obliczeń od rozwiązania najmniejszych podproblemów, zapisujemy rozwiązania w tablicy pomocniczej, a następnie używamy tych rozwiązań dla coraz to większych podproblemów, aż do uzyskania rozwiązania pełnego zadania.

Przykład – tzw. "problem plecakowy".

Metoda "zachłanna"- polega na rozpatrywaniu danych w kolejności uporządkowanej, np. posortowane. W danym kroku wybiera się te dane, które są najodpowiedniejsze, np. o najmniejszej wartości. Najczęściej metoda ta prowadzi do otrzymania rozwiązania

przybliżonego, choć istnieją problemy, dla których metoda zachłanna daje rozwiązanie optymalne.

Przykład - problem SST (Shortest Spanning Tree – najkrótsze drzewo spinające).

(9)

Pojęcie rekurencji - wieże z Hanoi

Francuski matematyk Edouard Lucas (rok 1883) - łamigłówka, klasyczne wprowadzenie zagadnienia rekurencji [Graham].

Należy przenieść całą wieżę krążków A na jeden z pozostałych prętów.

W każdym ruchu można brać tylko jeden krążek i nie wolno położyć większego krążka na mniejszym. Ile co najmniej ruchów należy wykonać, aby przenieść całą wieżę ?

(10)

Niech: Tn - minimalna liczba ruchów potrzebnych do przeniesienia n krążków z jednego pręta na drugi zgodnie z podanymi regułami - oczywiście T0= 0, T1= 1 i T2= 3

Ogólnie metodę przeniesienia n krążków można sformułować w następujący sposób:

- najpierw przenieś n – 1 krążków na pręt środkowy. Wymaga to wykonania Tn – 1ruchów, - następnie przenieś największy krążek na pręt docelowy (1 ruch),

- przenieś n – 1 krążków z pręta pomocniczego na pręt docelowy (znów Tn – 1ruchów).

Do przeniesienia n krążków (n > 0) potrzeba zatem co najwyżej 2Tn – 1+ 1 ruchów:

1 T 2 Tn n1

1 T 2 Tn n1

Próba znalezienia lepszego porównania prowadzi do stwierdzenia, że do przeniesienia n krążków potrzeba co najmniej 2Tn – 1+ 1 ruchów. Jest zatem:

dla n > 0

dla n > 0

Z tych nierówności oraz z rozwiązania trywialnego zadania z 0 krążkami wynika, że T0= 0

(11)

Jest to typowy przykład rekurencji (rekursji).

Aby znaleźć liczbę ruchów dla zadania z n krążkami należy wykonać podobne obliczenia kolejno dla 1, 2, . . . , n – 1 krążków.

Rekurencja musi mieć określoną wartość brzegową – tutaj T0 i z równania wyrażającego ogólną wartość z wartości wcześniej obliczonych.

Zalety rekurencji to eleganckie i zwięzłe formuły.

Wady to fakt, że implementacja programowa rekurencji posiada wiele ograniczeń natury technicznej.

Są to między innymi: ograniczona wielkość stosu, dodatkowe narzuty czasowe związane z

koniecznością odkładania na stosie i zdejmowania z niego kolejnych stanów procesora i śladów powrotu.

Wszędzie, gdzie tylko się da należy dążyć do wyeliminowania rekurencji.

(12)

W rozwiązaniu zadania o wieżach z Hanoi można wyeliminować rekurencję.

Rozważmy kilka "małych" zadań i spróbujmy obliczyć dla nich wartości Tn. Kolejno:

T3 = 23 + 1 = 7, T4 = 27 + 1 = 15, T5 = 2x15 + 1 = 31, T6 = 2x31 + 1 = 63

W zakresie wartości od 1 do 6 wygląda to jak Tn = 2n - 1 dla n  6.

Metodą indukcji matematycznej można wykazać, że zależność powyższa jest prawdziwa dla dowolnego n nieujemnego.

Bazą dowodu jest zależność dla n = 0: T0= 20- 1 = 0.

Krok indukcyjny dla n > 0 wynika gdy założymy, że zależność jest spełniona jeżeli n zastąpimy przez n – 1:

(13)

Podstawowe struktury danych

Do podstawowych struktur danych, na których najczęściej operują algorytmy należą:

• Zbiór,

• lista,

• graf,

• drzewo,

• słownik.

(14)

Lista (w matematyce odpowiada jej ciąg) to skończony ciąg elementów

Q = [x1, x2, . . . , xn].

Elementy skrajne x1oraz xnto jej końce - odpowiednio lewy i prawy.

Wielkość Q = n to długość listy. Szczególnym przypadkiem listy jest lista pusta Q = [ ].

Niech będą dane dwie listy: Q = [q1, q2, . . . , qn] i R = [r1, r2, . . . , rm.] oraz niech 0  i  j  n.

Podstawowe, abstrakcyjne operacje na listach to:

dostępdo elementu listy Q[i] = qi

podlista Q[i..j] = [qi, qi+1, . . . , qj]

złożenie(konkatenacja) Q & R = [q1, . . . , qn, r1, . . . , rm.]

Za pomocą tych trzech podstawowych operacji można definiować inne operacje, przykładowo:

1)insert(Q, x, i)= Q[1. . i] & [x] & Q[i+1. . Q] – wstawienie elementu x za element qina liście Q.

2)front(Q)= Q[1] - pobranie lewego końca listy.

3) rear(Q) = Q[Q] - pobranie prawego końca listy.

4) push(Q, x)= [x] & Q - wstawienie elementu x na lewy koniec listy, 5)pop(Q)= Q[2. . Q] - usunięcie aktualnego, lewego końca listy,

(15)

Lista, na której można wykonać wszystkie operacje 2 – 7 to kolejka podwójna.

Jeżeli na liście są zdefiniowane tylko operacje front, pop i push to jest ona stosem.

Lista, na której możemy wykonać tylko operacje front, pop i inject to kolejka.

Implementacje maszynowe listy: tablicowa Q[i] = qi

dowiązaniowa - każdy element listy (jej wierzchołek) zawiera oprócz danej również dowiązanie – adres następnego elementu).

Zbiór - jego elementy S = {x1, x2, . . . , xn}, inaczej niż w przypadku listy nie są ułożone w żadnym ustalonym porządku.

Zakładamy, że rozpatrywane zbiory są skończone.

Moc lub rozmiar Szbioru to liczba n jego elementów.

(16)

Podstawowe operacje na zbiorach to:

a) insert(x, S) - wstawienie elementu x do zbioru S: S := S  {x}

b) delete(x, S) - usunięcie elementu x ze zbioru S: S := S – {x}

c) member(x, S) - sprawdzenie, czy x jest elementem zbioru S,

funkcja ta ma wartość

d) min(S) - zwraca najmniejszy element w zbiorze S, przy założeniu pewnego ustalonego porządku liniowego 

e) max(S) - zwraca największy element w zbiorze S

f) deletemin(S), deletemax(S) - odpowiednio S := S - {min(S)}, S := S - {max(S)}

g) union(S

1

, S

2

) - oblicza S

1

 S

2

S x gdy false

S x gdy true

(17)

Najczęściej stosowane implementacje komputerowe zbioru to:

wektor charakterystyczny - jeżeli elementy zbioru S odpowiadają indeksom tablicy C to:

 

S x gdy false

S x gdy x true

C

implementacja listowa – jeżeli ustawimy elementy zbioru w jakimś porządku, to otrzymamy listę.

Każda implementacja listy może reprezentować zbiór.

Graf jest strukturą złożoną z dwóch zbiorów G = (V, E)

gdzie V jest skończonym zbiorem wierzchołków – w przypadku, gdy graf jest modelem struktury danych elementy zbioru V nazywa się węzłami.

E jest zbiorem krawędzi, tzn. par wierzchołków (węzłów) ze zbioru V.

W grafie zorientowanym zbiór E jest podzbiorem zbioru uporządkowanych par wierzchołków:

 

x , y : x , y V x y

(18)

 

2 1 n m n 

n 1

n m 

Rozmiar grafu G jest sumą dwóch liczb: n = |V| oraz m = |E|.

W grafie niezorientowanym krawędzie są nieuporządkowanymi parami wierzchołków.

W grafie niezorientowanym

a w zorientowanym

W algorytmach i programach komputerowych stosuje się dwa rodzaje implementacji grafu:

Listę sąsiedztwa

– dla każdego

x V

buduje się listę - oznaczoną jako L[x] - wierzchołków y będących sąsiadami x, tzn.

takich że (x, y)  E. Obszar pamięci potrzebny do zapamiętania tak przedstawionego grafu

zależy w sposób liniowy od rozmiaru grafu.

(19)

Macierz sąsiedztwa – macierz kwadratowa A o n wierszach i n kolumnach, taka że

 

 

E y x dla 0

E y x dla y 1

x

A , ,

, , ,

ten model grafu wymaga obszaru pamięci proporcjonalnego do n

2

Drzewo to odmiana grafu - jest to graf spójny acykliczny.

(20)

Złożoność algorytmów

Jak porównywać ze sobą różne algorytmy rozwiązujące tą samą klasę zadań ? W praktyce do porównywania algorytmów służy miara zwana złożonością.

Mówi się o złożoności czasowej i o złożoności przestrzennej.

W tym drugim przypadku – złożoność przestrzenna pozwala oszacować obszar pamięci potrzebny do przechowania danych i ew. pośrednich wyników obliczeń.

Klasę rozwiązywanych zadań charakteryzuje wielkość zwana rozmiarem zadania.

Jest to przeważnie liczba przetwarzanych danych.

(21)

Czasy działania najczęściej spotykanych w praktyce algorytmów są proporcjonalne do jednej z następujących funkcji:

stała 1 - algorytmy, w których większość operacji jest wykonywana tylko raz, bez względu na rozmiar zadania; mówimy, że ich czas działania jest stały.

log n - zależność ma charakter logarytmiczny - wzrost czasu działania w miarę wzrostu rozmiaru zadania jest nieznaczny. Taka zależność występuje w algorytmach, gdzie rozwiązywanie zadań polega na transformacji problemu na szereg podproblemów. Wartość log n podwaja się

dopiero po zwiększeniu n do n2.

n - zależność liczby operacji od rozmiaru zadania ma charakter liniowy; na każdy z n elementów wejściowych potrzebna jest mała ilość czasu przetwarzania. Jest to sytuacja optymalna dla algorytmów przetwarzających n elementów wejściowych.

n log n - algorytmy rozwiązują problem metodą jego dekompozycji na niezależne problemy o małym rozmiarze, a następnie łączą otrzymane rozwiązania. N.p. dla n = 1 000 000 wartość n log n przy podstawie 2 wynosi ok. 20 000 000.

n2 - zależność kwadratowa - w algorytmach, które muszą dokonać przeglądu wszystkich par n elementów (w algorytmie występują dwie "zagnieżdżone" pętle). Podwojenie rozmiaru zadania powoduje czterokrotny wzrost czasu działania.

n3 - zależność sześcienna – algorytmy przegładają wszystkie możliwe trójki danych (potrójna pętla). Algorytmy o takiej złożoności nadają się praktycznie do rozwiązywania tylko niewielkich zadań. Dwukrotne zwiększenie rozmiaru zadania powoduje aż ośmiokrotny wzrost czasu obliczeń.

2n - tylko niewiele algorytmów o złożoności wykładniczej znajduje zastosowanie praktyczne.

Podwojenie n powoduje "kwadratowy" wzrost czasu obliczeń.

(22)

Narzędzie matematyczne ułatwiające przeprowadzenie analizy algorytmów bez wnikania w szczegóły implementacyjne jest tzw. zapis z dużym "O" często w literaturze określany nazwą złożoności asymptotycznej.

Definicja tej miary jest następująca:

Funkcja g(n) jest rzędu O(f(n)), jeżeli istnieje taka stała rzeczywista c i liczba naturalna m, że dla każdego n > m zachodzi g(n) < c f(n).

Zapisu z dużym "O" używa się w celu:

- ograniczenia błędu popełnianego wskutek ignorowania małych członów wzorów matematycznych;

- ograniczenia błędu popełnianego wskutek ignorowania tych fragmentów programu,

które w małym stopniu przyczyniają się do wynikowej złożoności algorytmu;

(23)

Złożoność algorytmu wyszukiwania zadanego elementu w zbiorze n elementowym jest rzędu O(n), podobnie jak w przypadku poszukiwania minimum/maksimum w zbiorze.

Większość algorytmów sortowania ma złożoność rzędu O(n

2

).

Cytaty

Powiązane dokumenty

Średnie wyniki procentowe w podziale na obszary (test dodatkowy) Źródło: Opracowanie własne na podstawie wyników badania Omnibus W dalszej części tego artykułu skupię się

Celem realizacji Gminnego Programu Profilaktyki i Rozwiązywania Problemów Alkoholowych oraz Przeciwdziałania Narkomanii w roku 2015 było podniesienie poziomu wiedzy

macyjne takie jak m etoda włączania najdalszego wierzchołka FI oraz m etoda najtańszego włączania wierzchołka CI [20], [24], W algorytmach typu włączania najpierw

wana dla przedstawiciela danego typu technologicznego. Ze względu na różne wymiary przedm iotów czasy trwania poszczególnych operacji w marszrutach indywidualnych

Problem ten polega na sprawdzeniu, czy dla ustalonej wa rtości zmiennej progowej V, istnieje dopu sz cz al ny pr zy dz ia ł o koszcie V.. In tencją tej prscy Jest

W zwlęzku z tym do rozwięzanla problemu uzasadnione Jest wykorzystanie algorytmu opartego na koncepcji metod podziału i ograniczeń (b-a-b), w których wybór kolejnego

W kopertach wśród kartek tworzących treść zadania są przypadkowo dołożone treści, które albo nie zawierają żadnych istotnych informacji potrzebnych do rozwiązania, albo

Oblicz boki prostokąta ABCD, w którym przekątne mają po 8 cm, a kąt między przekątnymi