ALGORITMY. 0. krok (inicializace algoritmu): položme a 0 = a, b 0 = b. 2. krok: určíme zbytek r 1 (a 1, b 1 ) při dělení a 1



Podobné dokumenty
1 Mnohočleny a algebraické rovnice

1 Mnohočleny a algebraické rovnice

Polynomy. Mgr. Veronika Švandová a Mgr. Zdeněk Kříž, Ph. D. 1.1 Teorie Zavedení polynomů Operace s polynomy...

Pojem binární relace patří mezi nejzákladnější matematické pojmy. Binární relace

Vektory a matice. Obsah. Aplikovaná matematika I. Carl Friedrich Gauss. Základní pojmy a operace

Věta o dělení polynomů se zbytkem

Matematika 2 pro PEF PaE

Maticí typu (m, n), kde m, n jsou přirozená čísla, se rozumí soubor mn veličin a jk zapsaných do m řádků a n sloupců tvaru:

)(x 2 + 3x + 4),

10. Soustavy lineárních rovnic, determinanty, Cramerovo pravidlo

Matematika 1 MA1. 2 Determinant. 3 Adjungovaná matice. 4 Cramerovo pravidlo. 11. přednáška ( ) Matematika 1 1 / 29

Operace s maticemi. 19. února 2018

Pomocný text. Polynomy

8.3). S ohledem na jednoduchost a názornost je výhodné seznámit se s touto Základní pojmy a vztahy. Definice

ALGEBRA. 1. Pomocí Eukleidova algoritmu najděte největší společný dělitel čísel a a b. a) a = 204, b = 54, b) a = , b =

Necht tedy máme přirozená čísla n, k pod pojmem systém lineárních rovnic rozumíme rovnice ve tvaru

1 Linearní prostory nad komplexními čísly

(Cramerovo pravidlo, determinanty, inverzní matice)

a a

Definice 13.1 Kvadratická forma v n proměnných s koeficienty z tělesa T je výraz tvaru. Kvadratická forma v n proměnných je tak polynom n proměnných s


Matice. a m1 a m2... a mn

Matematika III. Miroslava Dubcová, Daniel Turzík, Drahoslava Janovská. Ústav matematiky

Determinanty. Obsah. Aplikovaná matematika I. Pierre Simon de Laplace. Definice determinantu. Laplaceův rozvoj Vlastnosti determinantu.

Základy matematické analýzy

[1] Determinant. det A = 0 pro singulární matici, det A 0 pro regulární matici

1 Vektorové prostory.

P 1 = P 1 1 = P 1, P 1 2 =

[1] Definice 1: Polynom je komplexní funkce p : C C, pro kterou. pro všechna x C. Čísla a 0, a 1,..., a n nazýváme koeficienty polynomu.

Funkce, elementární funkce.

V předchozí kapitole jsme podstatným způsobem rozšířili naši představu o tom, co je to číslo. Nadále jsou pro nás důležité především vlastnosti

Číselné vektory, matice, determinanty

MATICE. a 11 a 12 a 1n a 21 a 22 a 2n A = = [a ij]

Diskrétní matematika 1. týden

Lineární algebra : Polynomy

z = a bi. z + v = (a + bi) + (c + di) = (a + c) + (b + d)i. z v = (a + bi) (c + di) = (a c) + (b d)i. z v = (a + bi) (c + di) = (ac bd) + (bc + ad)i.

Aplikovaná numerická matematika - ANM

0.1 Úvod do lineární algebry

a počtem sloupců druhé matice. Spočítejme součin A.B. Označme matici A.B = M, pro její prvky platí:

Kapitola Základní množinové pojmy Princip rovnosti. Dvě množiny S a T jsou si rovny (píšeme S = T ) prvek T je také prvkem S.

3 Lineární kombinace vektorů. Lineární závislost a nezávislost

7. Funkce jedné reálné proměnné, základní pojmy

Polynomy nad Z p Konstrukce faktorových okruhů modulo polynom. Alena Gollová, TIK Počítání modulo polynom 1/30

Operace s maticemi

Úvod do informatiky. Miroslav Kolařík

Soustavy lineárních rovnic a determinanty

Matematika B101MA1, B101MA2

Algoritmizace. Jiří Vyskočil, Marko Genyg-Berezovskyj 2010

průniku podmnožin, spojení je rovno sjednocení podmnožin a komplement je doplněk Obr. 5: Booleovy algebry

0.1 Úvod do lineární algebry

maticeteorie 1. Matice A je typu 2 4, matice B je typu 4 3. Jakých rozměrů musí být matice X, aby se dala provést

Algoritmus. Přesné znění definice algoritmu zní: Algoritmus je procedura proveditelná Turingovým strojem.

Limita a spojitost funkce a zobrazení jedné reálné proměnné

Definice. Vektorový prostor V nad tělesem T je množina s operacemi + : V V V, tj. u, v V : u + v V : T V V, tj. ( u V )( a T ) : a u V které splňují

9 Kolmost vektorových podprostorů

Lineární algebra : Polynomy

4 Počítání modulo polynom

Časová složitost / Time complexity

pouze u některých typů rovnic a v tomto textu se jím nebudeme až na

Kapitola 11: Vektory a matice:

VI. Maticový počet. VI.1. Základní operace s maticemi. Definice. Tabulku

Množiny, relace, zobrazení

Matematika (CŽV Kadaň) aneb Úvod do lineární algebry Matice a soustavy rovnic

Báze a dimenze vektorových prostorů

LDF MENDELU. Simona Fišnarová (MENDELU) LDR druhého řádu VMAT, IMT 1 / 22

12. Determinanty. 12. Determinanty p. 1/25

ALGEBRA. Téma 4: Grupy, okruhy a pole

zejména Dijkstrův algoritmus pro hledání minimální cesty a hladový algoritmus pro hledání minimální kostry.

Cykly a pole

LEKCE10-RAD Otázky

1. Několik základních pojmů ze středoškolské matematiky. Na začátku si připomeneme následující pojmy:

10. DETERMINANTY " # $!

SOUČIN MATIC A m n B n p = C m p, přičemž: a i1 b 1j +a i2 b 2j + +a in b nj = c ij, i=1 m, j=1 p. Např: (-2) = -3

Diferenciální rovnice 3

Lineární algebra : Násobení matic a inverzní matice

Lineární algebra : Násobení matic a inverzní matice

0.1 Úvod do matematické analýzy

POSLOUPNOSTI A ŘADY INVESTICE DO ROZVOJE VZDĚLÁVÁNÍ. Tento projekt je spolufinancován Evropským sociálním fondem a státním rozpočtem České republiky

Numerická matematika 1

10. N á h o d n ý v e k t o r

Lineární algebra Operace s vektory a maticemi

POSLOUPNOSTI A ŘADY INVESTICE DO ROZVOJE VZDĚLÁVÁNÍ

Pojem algoritmus. doc. Mgr. Jiří Dvorský, Ph.D. Katedra informatiky Fakulta elektrotechniky a informatiky VŠB TU Ostrava

Univerzita Karlova v Praze Pedagogická fakulta

Determinanty. Determinanty. Přednáška MATEMATIKA č. 3. Jiří Neubauer

Vektorové podprostory, lineární nezávislost, báze, dimenze a souřadnice

2.6. VLASTNÍ ČÍSLA A VEKTORY MATIC

1 Determinanty a inverzní matice

Afinita je stručný název pro afinní transformaci prostoru, tj.vzájemně jednoznačné afinní zobrazení bodového prostoru A n na sebe.

Algoritmy I, složitost

Posloupnosti a jejich limity

[1] x (y z) = (x y) z... (asociativní zákon), x y = y x... (komutativní zákon).

Nejdřív spočítáme jeden příklad na variaci konstant pro lineární diferenciální rovnici 2. řádu s kostantními koeficienty. y + y = 4 sin t.

Interpolace, ortogonální polynomy, Gaussova kvadratura

Dosud jsme se zabývali pouze soustavami lineárních rovnic s reálnými koeficienty.

(4x) 5 + 7y = 14, (2y) 5 (3x) 7 = 74,

CVIČNÝ TEST 5. OBSAH I. Cvičný test 2. Mgr. Václav Zemek. II. Autorské řešení 6 III. Klíč 17 IV. Záznamový list 19

a vlastních vektorů Příklad: Stanovte taková čísla λ, pro která má homogenní soustava Av = λv nenulové (A λ i I) v = 0.

Matematická analýza ve Vesmíru. Jiří Bouchala

Transkript:

ALGORITMY V této části si přiblížíme jeden ze základních pojmů informatiky, a to pojem algoritmus. Vyhneme se přesné definici, vystačíme s intuitivní definicí pojmu algoritmus tak, že se konstatujeme, že algoritmus je přesný, úplný a jednoznačný návod jak řešit daný problém. Každý algoritmus je tedy spojen s řešením nějakého konkrétního problému. Řešit algoritmicky nějakou úlohu znamená, že zadané vstupní hodnoty (přípustného tvaru) jsou nějakým způsobem zpracovávány a po konečném počtu kroků jsou získány nějaké výstupní hodnoty (v požadovaném tvaru). Základní požadavek na algoritmus je jeho jednoznačnost, což znamená, že ze stejných vstupních hodnot jsou vždy získány stejné výstupy. Postup, který vybere náhodně jednu z číslic {0, 1,,, 4} není (v přísně exatní definici algoritmu) algoritmem. Pro zjednodušení a praktičnost se často náhodný výběr považuje za přijatelný algoritmický krok. Euklidův algoritmus Slovo algoritmus je odvozeno od jména perského matematika, který žil v 9. století a který se jmenoval Muhammad al Khwarizmí. Latinský přepis jeho jména je Algoritmus. Tento matematik se zabýval především pravidly pro operace s čísly. Algoritmické postupy byly známy dlouho před životem tohoto matematika. Jeden ze známých algoritmů, tzv. Euklidův algoritmus pro výpočet nějvětšího společného dělitele dvou přirozených čísel, pochází dokonce ze 4. století před naším letopočtem. Je to nejstarší známý netriviální algoritmus, který je připisován právě řeckému matematikovi Euklidovi (žil 65 00 před n.l.). Ukažme si, jak pracuje tento Euklidův postup pro výpočet největšího společného dělitele ND(a, b) dvou přirozených čísel a, b, kde a > b. Předem připomeňme, že jsouli m, n přirozená čísla (tj. m, n N), pak existují jednoznačně určená přirozená čísla s, r(m, n) N {0}, tak, že je m = n s + r(m, n) a r(m, n) < n. Číslo r(m, n)je zbytek při dělení m n. 0. krok (inicializace algoritmu): položme a 0 = a, b 0 = b. 1. krok: Určíme zbytek r 0 (a 0, b 0 ) při dělení a 0 b 0. Jestliže je r 0 (a 0, b 0 ) = 0, je ND(a, b) = b 0. Je li r 0 (a 0, b 0 ) 0, položme a 1 = b 0 a b 1 = r(a 0, b 0 ).. krok: určíme zbytek r 1 (a 1, b 1 ) při dělení a 1 b 1. Je li r 1 (a 1, b 1 ) = 0, je ND(a, b) = b 1. Je li r 1 (a 1, b 1 ) 0, položme a = b 1 a b = r(a 1, b 1 ). Takto pokračujeme tak dlouho, až postup skončí, tj. postup skončí v okamžiku, kdy je r i (a i, b i ) = 0. Potom je ND(a, b) = b i. Zmíněný postup si nyní ilustrujme na konkrétním příkladě. Získané hodnoty jsou uvedeny v následující tabulce. i 1 4 5 a i 100 57 5 105 4 b i 57 5 105 4 1 r i (a i, b i ) 5 105 4 1 0 Vidíme, že výpočet skončil v 5. kroku a je ND(100, 57) = 1. Při tomto postupu jsme potřebovali pouze schopnost dělit dvě přirozená čísla se zbytkem. Kdybychom neuměli dělit, musel by být algoritmus formulován jinak. Krok urči zbytek r(m, n) při

dělení m n dvou přirozených čísel m, n, m > n by bylo možno nahradit například tímto algoritmem: 0. krok (inicializace algoritmu): položme x 0 = m. 1. krok: Určíme rozdíl x 1 = x 0 n. Jestliže je x 1 < n, je r(m, n) = x 1 Není li x 1 < n, položme x = x 1.. krok: Určíme rozdíl x = x 1 n. Jestliže je x < n, je r(m, n) = x Není li x < n, položme x = x. Takto pokračujeme tak dlouho, až postup skončí, tj. postup skončí v okamžiku, kdy je x i < n. Potom je r(m, n) = x i. Poznamenejme na tomto místě, že původní Euklidův algoritmus byl založen právě na tomto postupu postupného odečítání menšího čísla od většího. Hornerovo schema Dalším klasickým algoritmickým postupem je postup pro výpočet hodnot polynomu, který je znám v literatuře jako Hornerovo schema. Mějme polynom n tého stupně P (x) = a 0 x n + a 1 x n 1 + + a n 1 x + a n. Naším úkolem je nyní určit hodnotu tohoto polynomu v daném bodě c, tj. máme určit P (c) = a 0 c n + a 1 c n 1 + + a n 1 c + a n. Vstupními údaji pro výpočet P (c) jsou údaje: a 0, a 1,..., a n 1, a n a c. Hornerovo schema je založeno na postupném výpočtu nových hodnot b 0, b 1,..., b n 1, b n podle předpisu: b 0 = a 0, b 1 = a 1 + b 0 c,..., b i = a i + b i 1 c,... b n = a n + b n 1 c. Závěr výpočtu je b n = P (c). Při konkrétním výpočtu si hodnoty zapisujeme do tabulky a 0 a 1 a a n c b 0 c b 1 c b n 1 c b 0 b 1 b b n = P (c) Ukažme si jeden konkrétní příklad. Určeme pomocí Hornerova schematu hodnotu polynomu P (x) = x 4 + x x +x 7 v bodě x =. Mezivýpočty budeme zapisovat přímo do tabulky. 1 1 7 4 14 6 54 7 1 7 47 Hodnota polynomu P (x) = x 4 + x x + x 7 v bodě x = je 47. Nyní si ukažme správnost Hornerova schematu. To je poměrně velmi jednoduché. Polynom P (x) = a 0 x n +a 1 x n 1 + +a n 1 x+a n je možno vyjádřit také následujícími způsoby: P (x) = (a 0 x + a 1 ) x n 1 + a x n + + a n 1 x + a n P (x) = ((a 0 x + a 1 ) x + a ) x n + + a n 1 x + a n P (x) = (((a 0 x + a 1 ) x + a ) x + a ) x n + + a n 1 x + a n..

P (x) = ( ((((a 0 x + a 1 ) x + a ) x + a ) x + a 4 ) x + + a n 1 ) x + a n Hodnota polynomu v bodě x = c je P (c) = ( ((((a 0 c + a 1 ) c + a ) c + a ) c + a 4 ) c + + a n 1 ) c + a n P (c) = ( (((b 1 c + a ) c + a ) c + a 4 ) c + + a n 1 ) c + a n P (c) = ( ((b c + a ) c + a 4 ) c + + a n 1 ) c + a n P (c) = ( (b c + a 4 ) c + + a n 1 ) c + a n. P (c) = b n 1 c + a n P (c) = b n Koeficienty b 0, b 1,..., b n 1 jsou koeficienty polynomu Q(x), který dostaneme při dělení polynomu P (x) polynomem x c se zbytkem. Platí totiž, že P (x) = (x c) Q(x) + m, kde Q(x) je nějaký polynom stupně n 1. Skutečně, je li polynom Q(x) zadán předpisem Q(x) = d 0 x n 1 + d 1 x n + + d n x + d n 1, pak musí platit rovnosti ( které dostaneme porovnáním koeficientů u jednotlivých mocnin): a 0 = d 0, a 1 = d 1 c a 0, a = d c d 1,..., a n = m c d n 1, nebo li d 0 = a 0, d 1 = a 1 +c d 0, d = a +c d 1,..., d n 1 = a n 1 +c d n, m = a n +c d n 1. Koeficenty d 0, d 1,..., d n 1 jsou stejné jako čísla b 0, b 1,..., b n 1 a m = P (c). Hornerovo schema je tedy možno použít pro dělení polynomů polynomem x c. Další zajímavý důsledkek je to, že hodnota derivace polynomu P (x) je rovna Q(c). Je li totiž P (x) = (x c) Q(x)+m, pak je P (x) = Q(x)+(x c) Q (x) a následně je P (c) = Q(c). Budeme li pokračovat ve stejné úvaze dále, dostaneme, že Q(x) = (x a) R(x) + s pro nějaký polynom R(x) a nějaké číslo s. Určeme dále druhou derivaci polynomu P (x). Je P (x) = (Q(x) + (x c) Q (x)) = Q (x) + Q (x) + (x c) Q (x). Odsud dostaneme P (c) = Q (c) = R(c), tj. R(c) = P (c). Hornerovo schema je možno tedy použít i pro výpočet hodnot derivací všech řádů polynomu P (x) v bodě c. Ukažme si to na příkladě. Máme polynom P (x) = x 4 + x 5x + 7x 9. Pomocí Hornerova schematu určeme P (), P (), P (), P () a P (4) ().

4 5 7 9 4 14 18 50 7 9 5 41 = P () 4 6 11 1 87 = P () 1! 4 0 15 61 = P ()! 4 19 = P ()! = P (4) () 4! Z tabulky vidíme, že je P () = 4, P () = 1! 87 = 87, P () =! 61 = 1, P () =! 19 = 114 a P (4) () = 4! = 48. Požadavky na algoritmus Algoritmus musí být vždy přesný, úplný a jednoznačný návod, jak daný problém řešit v konečně mnoha krocích s použitím prostředků, které jsou k dispozici. Základní požadavky kladené na každý algoritmus jsou: 1. Správnost algoritmu. Nejzákladnějším požadavkem kladeným na každý algoritmus je jeho správnost. U každého algoritmu by měla být dokázána jeho správnost podobně jako v matematice jsou dokazována tvrzení, věty a vzorce. Nestačí nahradit důkaz správnosti tím, že v testovacím provozu dává správné výsledky.. Konečnost algoritmu. Každý algoritmus musí skončit v konečném počtu kroků. Tento počet kroků může být libovolně velký (podle rozsahu a hodnot vstupních údajů), ale vždy musí být konečný.. Determinovanost (jednoznačnost) algoritmu. Každý krok algoritmu musí být jednoznačně a přesně definován. V každé z možných situací musí být naprosto jednoznačně určeno jak má provádění algoritmu pokračovat. 4. Obecnost algoritmu. Algoritmus má řešit obecný problém, ne tedy pouze jednu jedinou úlohu s jedinými možnými vstupy. Algoritmus musí být použitelný pro řešení celé třídy obdobných problémů. 5. Resultativnost algoritmu. Každý algoritmus zpracovává nějaké vstupní údaje, tj. nějaké veličiny které mu jsou předány před započetím jeho provádění, a po jejich zpracování dává výstupní údaje (alespoň jeden), které tvoří odpověď na problém algoritmem řešený. Jako ukázku si ukažme, že tyto vlastnosti má výše uvedený Euklidův algoritmus. Důkaz správnosti algoritmu je založen na evidentním poznatku, že pro každá dvě přirozená čísla

m a n, m > n platí: je li m = n s + r(m, n) pro nějaké s N a r(m, n) < n, pak je ND(m, n) = n v případě, že je r(m, n) = 0 a ND(m, n) = N(n, r(m, n)) v případě, že není r(m, n) = 0. V našem algoritmu proto v každém kroku platí: je li r i (a i, b i ) = 0, je ND(a, b) = b i a je li r i (a i, b i ) 0, je ND(a, b) = ND(a i, b i ) = ND(b i, r(a i, b i )) = ND(a i+1, b i+1 ). Euklidův algoritmus musí skončit po konečně mnoha krocích, protože posloupnost čísel b i je klesající a, tj. je b 1 > b > > b i 1. V každém kroku algoritmu mohou nastat pouze dvě možnosti a v obou je jasné, jak pokračovat. Je li r i (a i, b i ) = 0, algoritmus končí a je ND(a, b) = b i. Je li r i (a i, b i ) 0, pokračuje algoritmus s hodnotami a i+1 = b i a b i+1 = r(a i, b i ). Algoritmus je plně obecný, platný a použitelný pro každou dvojici přirozených čísel m a n, m > n. Výstupem algoritmu je jedno jednoznačně určené přirozené číslo ND(m, n), což je největší společný dělitel přirozených čísel m a n. Složitost algoritmu Pro řešení konkrétních algorotmicky řešitelných úloh je možno nalézt více správných algoritmů, které problém řeší. Tím přichází další problém výběru algoritmu, a to problém určit který z nich je pro danou potřebu vhodný. Proto jednou z velmi důležitýchch vlastností jakéhokoliv algoritmu je jeho složitost. Pod pojmem složitost není myšlena kvalita či způsob jeho formulace, ale doba jeho trvání či jeho náročnost na paměť resp. množství uchovávaných mezivýsledků. Složitost algoritmu je možno posuzovat ze dvou základních hledisek. Jsou to hlediska jak dlouho algoritmus běží nebo jaké množství údajů si algoritmus ponechává pro další použití. V prvním případě hovoříme o časové složitosti algoritmu, ve druhém případě o prostorové složitosti algoritmu. Složitost algoritmu závisí na velikosti vstupních dat a je proto dobré odhadnout poté co si ověříme jeho správnost. Jistě v konkrétních příkladech také doba trvání algoritmického výpočtu závisí na kvalitě počítačů a kompilátoru, které jsou pro realizaci algoritmu použity. Časovou složitostí algoritmu se proto rozumí počet nutných elementárních operací, které je nutno vykonat pro zpracování n vstupních údajů. Nebude nás zajímat ale skutečný počet těchto operací, ale spíše nějaký jejich odhad. Bude li například časová složitost algoritmu dána vzorcem T (n) = a n + b, pak budeme spokojeni s konstatováním, že časová složitost algoritmu je lineární a nebudou nás příliš zajímat velikosti konstant a, b. Otázky týkající se složitosti algoritmu jsou velmi složité, je možno kromě horního odhadu (tj. složitost v nejhorším případě) studovat i složitosti v nějakém normálním (statisticky průměrném) případě. všemi těmito otázkami se nebudeme zabývat, v dalším vystačíme s horním odhadem časové složitosti algoritmu. Definice. Nechť g(n) je nějaká funkce proměnné n N. Řekneme, že funkce T (n) je složitosti O(g(n)), což budeme zapisovat vztahem T (n) O(g(n)), jestliže existuje přirozené číslo n 0 a reálné číslo k tak, že pro každé n N, n n 0 je T (n) k g(n). Například je li T (n) = a n+b, pak je T (n) = a n+b (a+ b ) n. Je tedy T (n) O(n). Je li T (n) = a n + b n + c, pak je obdobně T (n) = a n + b n + c ( a + b + c ) n a platí tedy: T (n) O(n ). Zcela anologicky lze ukázat, že pro každou funkci T (n), která je dána předpisem T (n) = a 0 n k + a 1 n k 1 + + a k 1 n + a k pro nějaké a i R, je T (n) = O(n k ). Poznámka. Složitost funkce, tak jak jsme ji definovali má v sobě jistou volnost. Protože je n n n 4, je každá funkce, která je složitosti O(n ) je také složitosti O(n ), O(n 4 ) atd. Proto se zavádí pro hodnocení složitosti algoritmů přesnější symbol, a to symbol θ. 5

6 Definice. Nechť g(n) je nějaká funkce proměnné n N. Řekneme, že funkce T (n) je složitosti θ(g(n)), což budeme zapisovat T (n) θ(g(n)), jestliže je T (n) O(g(n)) a zároveň je g(n) O(T (n)). Je li T (n) θ(g(n)), říkáme, že funkce g(n) a T (n) si jsou asymptoticky rovny. Funkce T (n) = n + 7n + 6 je, jak již víme, složitosti O(n ). Protože též platí, že n n + 7n + 6, je n O(T (n)), a tedy funkce T (n) a n si jsou asymptonicky rovny. Platí tedy, že je T (n) θ(n ) což je mnohem silnější informace než informace T (n) O(n ). Ukažte, že není T (n) θ(n ). Přesto, že symbol θ vyjadřuje složitost algoritmu lépe, my v dalším vystačíme s horním odhadem pomocí symbolu O. Budeme se ale snažit, aby tento odhad byl co nejlepší. I když je možno uměle konstruovat algoritmy s různými časovými složitostmi, my v dalším většinou vystačíme s následujícími časovými složitostmi algoritmů: O(log n), O(n), O(n log n), O(n ), O(n log n), O(n ), O( n ) a O(n!). Algoritmům, které mají složitost O(n), O(n ) a O(n ), říkáme postupně lineární, kvadratické a kubické algoritmy. Souhrně algoritmy, které mají složitost O(n k ), nazýváme polynomiální algoritmy. Algoritmy, které mají složitost O( n ) se nazývají exponenciální algoritmy. Mezi polynomiální algoritmy se počítají též algoritmy se složitosí O(n log n), O(n log n) apod., a to proto, že je log n < n. Uvvďme si některé základní vlastnosti funkce O. Jsou to vlastnosti: k O(f(n) = O(f(n)) O(f(n)) + O(f(n)) = O(f(n)) O(O(f(n))) = O(f(n)) O(f(n)) O(g(n)) = O(f(n) g(n)) O(f(n) g(n)) = f(n) O(g(n)) Všimněme si, že hovoříme li o tom, že je nějaký algoritmus logaritmické složitosti, není nutno uvádět základ logaritmu. Platí totiž log a x = ln x ln a. Odsud lze ihned odvodit známý převodní vztah (platný pro libovolné základy logaritmů a, b (0, 1) (1, )) log a x = ln b ln a log bx. Podle prvního pravidla jsou si logaritmické funkce f(n) = log a (n) a g(n) = log b (n) asymptoticky rovny. Poznámka. I když se zdá, že otázky složitosti počítačů jsou v dnešní době zanedbatelné z důvodu existence vysoce rychlých a kapacitně bohatých výpočetních prostředků, není to zcela pravda. Jisté je, že v případě malého počtu zpracovávaných dat je celkem jedno, jakým algoritmem jsou zpracovávána. Nemusí to být pravda, a to zejména při používání algoritmů nepolynomiální složitosti. V následující tabulce jsou uvedeny časy potřebné ke zpracování n vstupních dat při použití algoritmu složitosti T (n) a to za předpokladu, že je za 1 sec. zpracován 1 milion operací.

7 T (n) 10 0 0 40 50 n 10 µs 0 µs 0 µs 40 µs 50 µs n 0, 1 ms 0, 4 ms 0, 9 ms 1, 6 ms, 5 ms n 1 ms 8 ms 7 ms 64 ms 15 ms n 1 ms 1 s 17, 9 min 1, 7 dne 5, 7 let n!, 6 s 77 tis. let 8, 4 10 18 let, 5 10 4 let 9, 6 10 50 let Jako příklad si uveďme následující problém. Víme, že heslo pro vstup do nějaké aplikace se skládá přesně z 10 číslic 0, 1,,, 4, 5, 6, 7, 8 a 9 a desíti písmen A,B,C,D,E,F,G,H, I a J a žádný ze symbolů se neopakuje. Máme tedy přesně 0! možností pro toto heslo. Pokud za 1 sec. vyzkoušíme 1 milion hesel, máme zaručenu úspěšnost proniknutí do aplikace až po cca 77 000 letech. Jiným příkladem by mohl být algoritmus výpočtu determinantu čtvercové matice založený na definici determinantu. Připomeňme si tuto definici a definice dalších potřebných pojmů. Permutací množiny {1,,..., n} rozumíme každé prosté zobrazení této množiny na sebe. Takovýchto zobrazení existuje přesně n! (n faktoriál). Je-li π permutace množiny {1,,..., n}, pak její obraz lze vyjádřit posloupností π(1), π(),..., π(n). Pro vyjádření permutace se také často používá následující zápis π = ( 1... n π(1) π()... π(n) Množinu všech permutací množiny {1,,..., n} označíme symbolem Π n. Inverzí v permutaci π rozumíme každou dvojici i, j přirozených čísel z {1,..., n} takovou, že platí: i < j a π(i) > π(j). Permutaci nazýváme lichou nebo sudou podle toho, zda její počet inverzí je číslo liché nebo sudé. Znaménkem permutace π budeme rozumět číslo zn π = ( 1) k, kde k je počet inverzí v permutaci π. Příkladem sudé permutace je třeba permutace identická (k = 0) nebo první z níže uvedených permutací (k = 10); příkladem liché permutace je druhá z uvedených permutací (k = 1). π 1 = ( 1 4 5 5 4 1 ), π = ). ( 1 4 5 1 5 4 Nyní již můžeme přistoupit k definici determinantu čtvercové matice. Definice. Determinantem čtvercové matice a 11 a 1... a 1n a A = 1 a... a n...... a n1 a n... a nn řádu n rozumíme reálné číslo det A = π Π n zn π a 1π(1) a π() a nπ(n). ).

8 Algoritmus výpočtu determinantu čtvercové matice řádu n založený na definici by vyžadoval určit všechny permutace množiny {1,,..., n}, určit jejich znaménka, vypočítat součiny zn π a 1π(1) a π() a nπ(n) a všechny takto získané sčítance sečíst. Protože se jedná o n! sčítanců, trval by výpočet až nereálně dlouho. Existují i jednoduše formulované algoritmy jejichž složitost nelze v některých případech omezit žádným horním odhadem závislým na počtu vstupních veličin. Jako příklad si vezměme Euklidův algoritmus v modifikaci postupného odečítání čísel. Tak k určení zbytku při dělení čísla 105 číslem budeme potřebovat 51 kroků. Samozřejmě lze ke každému přirozenému číslu n číslo (např. n + ) které bude vyžadovat při určování zbytku při dělení číslem (metodou odečítání čísla ) více než n kroků. Zejména v takovýchto případech je velmi důležité jakým algoritmem úlohu řešíme a každé zjednodušení je velice cenné. Mnohá zjednodušení využívají (a musí využívat) i hluboké teoretické výsledky z disciplín, kterých se algoritmus týká. Například při výpočtu determinantů čtvercových matic lze využít následující větu týkající se úprav s řádky matice. Věta. Nechť A je čtvercová matice. Platí: 1) jestliže matice B vznikne z matice A záměnou přesně dvou řádků matice A, pak det B = det A; ) jestliže matice B vznikne z matice A vynásobením některého řádku matice A číslem r, pak det B = r det A; ) jestliže matice B vznikne z matice A přičtením r násobku nějakého řádku matice A k jinému řádku matice A, pak det B = det A; 4) má-li matice A pod hlavní diagonálou samé nuly, pak det A je roven součinu prvků na diagonále; 5) jestliže matice A obsahuje řádek nebo sloupec složený ze samých nul, je det A = 0. Výběrové a třídící algoritmy Ukažme si, na několika příkladech jednoduchých algoritmů, jak určovat složitost algoritmů. Ukážeme si to na příkladě výběrového algoritmu a na příkladech tzv. třídících algoritmů. Výběrové a třídící algoritmy patří mezi velmi aplikovatelné algoritmy. V podstatě jde o velmi přirozený požadavek z daných objektů vybrat objekt s nějakou extrémní hodnotou resp. danou množinu objektů uspořádat vzestupně (resp. sestupně) podle nějakého parametru vzhledem k nějakému úplnému uspořádání. Například je potřeba vybrat nebo setřídit výrobky podle ceny, váhy, data výroby apod. Jestliže abecedně (nebo jinak) seřazeným výrobkům přiřadíme jejich ceny, dostaneme seznam jejich cen, což nemusí být množina protože ceny různých výrobků mohou být stejné. Naším úkolem je tento soubor dat přetvořit v uspořádaný seznam. V seznamech záleží na pořadí jednotlivých prvků (na rozdíl od množin, které jsou zadány výčtem prvků) a připouští se i opakovaný výskyt stejné hodnoty (což se nepřipouští v množinovém výčtu). Pro jednoduchost bedeme dále předpokládat, že máme seznam n přirozených čísel A = {a 1, a,..., a n }. Naším úkolem je tento seznam přetvořit v uspořádaný seznam B = {b 1, b,..., b n }, kde pro každé i je b i A a b i b i+1. Výběr nejmenšího prvku Řešit algoritmicky úlohu vybrat z daného seznamu A = {a 1, a,..., a n } prvek s nejmenší (nebo největší) hodnotou je velice jednoduché. Je možno postupovat například podle tohoto návodu (algoritmu). Výsledek algorimu bude prvek b jednoprvkové množiny B n = {b}, kterou budeme tvořit v každém kroku následujícím způsobem:

1. krok: položíme b 1 = a 1, je tedy B 1 = {a 1 };. krok: porovnáme prvky a a b. Je li a b, ponecháme množinu B 1 = {b 1 } beze změny, bude B = B 1. Je li ale a < b, nahradíme prvek b 1 prvkem a. Bude tedy B = {a }; i tý krok: v tomto kroku porovnáme prvky a i a b i 1. Je li a i b i 1, ponecháme množinu B i 1 = {b i 1 } beze změny, bude B i = {b i 1. Je li ale a i < b i 1, nahradíme prvek b i 1 prvkem a i. Bude tedy B i = {a i }; n tý krok: v tomto kroku porovnáme prvky a n a b n 1. Je li a n b n 1, ponecháme množinu B n 1 = {b n 1 } beze změny, bude B n = {b n 1. Je li ale a n < b, nahradíme prvek b n 1 prvkem a n. Bude tedy B n = {a n }. Toto je poslední krok algoritmu a jeho výstupem je prvek b n B n. Poznámka. Samozřejmě, že není nutno indexovat množinu B = {b}, to děláme pro větší srozumitelnost. Ukažme si tuto metodu na jednom příkladě. Mějme dánu množinu A = {8, 5, 4,, 7, 5, 1, 9}. V následující tabulce je uvedeno, jak se mění výstupní hodnota po provedení i tého kroku. Hledaná nejmenší hodnota je 1. krok 1 4 5 6 7 8 A 8 5 4 7 5 1 9 B 8 5 4 1 1 Protože pro provedení algoritmu bylo potřeba n kroků (při n vstupních hodnotách), je časová složitost algoritmu O(n), přesněji θ(n). Třídění přímým vkládáním Nejjednodušší metoda třídění kterou běžně používáme je tzv. metoda přímého vkládání. Metoda spočívá v tom, že vytváříme uspořádaný seznam objektů tak, že postupně zařazujeme objekty mezi již uspořádané tak, aby byla zachováno uspořádání. Algoritmus je možno formulovat takto: (inicializace algoritmu) máme A 0 = {a 1, a,..., a n } a B =. 1. krok: první číslo seznamu A 0 = {a 1, a,..., a n } vyjmeme a zařadíme na první místo vytvářeného seznamu B 1, tj. určíme, že je b 1 = a 1. Po provedení tohoto kroku budeme mít dva seznamy, a to A 1 = {a,..., a n } a B 1 = {b 1 }.. krok: první číslo seznamu A 1 = {a,..., a n } vyjmeme a porovnáme ho s číslem b 1. Je li a b 1, dáme ho na první místo seznamu B a dosavadní první prvek seznamu B 1 dáme na místo druhé. Bude tedy B = {a, a 1 }. Je li a > b 1, zařadíme prvek a na druhé místo seznamu B. V tomto případě bude tedy B = {a 1, a }. Po provedení tohoto kroku bude A = {a,..., a n } a B = {b 1, b }. i tý krok: první číslo seznamu A i 1 = {a i,..., a n } vyjmeme a porovnáme ho postupně (od prvního) se všemi čísly seznamu B i 1. Je li j první (tj. nejmenší) číslo takové, že je a i b j, dáme ho na j té místo seznamu B a prvky {b j, b j+1,... } seznamu B posuneme o jedno místo dozadu. Bude tedy B i = {b 1..., b j 1, a i, b j,... }. Je li prvek a i větší než všechny prvky seznamu B, zařadíme prvek a i na poslední místo seznamu B. V tomto případě bude tedy B = {b 1, b,..., b i, a i }. Po provedení tohoto kroku bude A i = {a i+1,..., a n } a B = {b 1, b,... b i }. 9

10 n tý krok (konec algoritmu): algoritmus končí po n krocích, A = a B n je hledaný uspořádaný seznam. Pokud za elementární úkon algoritmu vezmeme porovnávání dvou čísel, musíme provést těchto elementárních úkonů (v nejhorším případě) celkem N = 0 + 1 + + + n 1 = n (0 + n 1) = 1 n 1 n. Popsaný algoritmus je časové složitosti O(n ), přesněji θ(n ). Ukažme si ještě algoritmus třídění přímým vkládáním na konkrétním příkladě. Jako výchozí seznam mějme seznam přirozených čísel {, 5, 7, 1,, 8, 1, 16,,, 9}. V následující tabulce jsou v řádcích uvedeny výsledky algoritmu po jednotlivých krocích. A 0, 5, 7, 1,, 8, 1, 16,,, 9 B 0 A 1 5, 7, 1,, 8, 1, 16,,, 9 B 1 A 7, 1,, 8, 1, 16,,, 9 B, 5 A 1,, 8, 1, 16,,, 9 B, 5, 7 A 4, 8, 1, 16,,, 9 B 4 1,, 5, 7 A 5 8, 1, 16,,, 9 B 5 1,,, 5, 7 A 6 1, 16,,, 9 B 6 1,,, 5, 7, 8 A 7 16,,, 9 B 7 1,,, 5, 7, 8, 1 A 8,, 9 B 8 1,,, 5, 7, 8, 1, 16 A 9, 9 B 9 1,,,, 5, 7, 8, 1, 16 A 10 9 B 10 1,,,,, 5, 7, 8, 1, 16 A 11 B 11 1,,,,, 5, 7, 8, 9, 1, 16 Poznámka. při určování složitosti algoritmu není nutno elementární kroky počítat zcela přesně, někdy je to velmi obtížné. V našem případě to bylo jednoduché, mohli jsme použít vzorec pro výpočet součtu prních n členů aritmetické posloupnosti. Obvykle lze vystačit se zjednodušenými úvahami typu: je nutno provést nejvýše n kroků, při každém kroku je nutno provést maximálně n elementárních úkonů a tedy k výpočtu je nutno provést maximálně n n elementárních úkonů. Algoritmus je tedy časové složitosti maximálně O(n ). Při takto zjednodušených úvahách ovšem hrozí nebezpečí, že neodhadneme dobře minimální složitost. Při určování složitosti funkcí T (n) můžeme využít i jiné prostředky matematiky. Ukažme si jeden příklad. Mějme funkci T (n) = 1 + + + +n. Protože je evidentně 1 n, n, n,..., n n, je také T (n) = 1 + + + +n n n = n. Proto platí: T 9n) O(n ). Zůstává ale otázka, zda toto zařazení funkce T (n) do třídy O(n ) nelze zlepšit, tj. zda také platí T (n) θ(n ). Provedeme tuto úvahu: pro x 0, 1 1 1 je 0 x 1, a proto je následně x dx 1 dx = 1. Obdobně je pro x 1, je 1 x, a tedy i n n 1 x dx Protože je n n 1 x dx 1 0 0 dx = ; obdobně je 1 x dx n dx =. Sečtením všech nerovnic dostaneme nerovnici n x dx = 0 dx =, až n x dx 1 + + + + n = T (n). 0 [ ] n x = n n, dostáváme, že je T (n). To dává, spolu s již 0 známým vztahem T (n) n, platnost vztahu T (n) θ(n ).

Třídění sléváním Základní myšlenka algoritmu, který je nazýván třídění sléváním (nebo slučováním anglicky mergesort) je velmi jednoduchá. Je založena na tom, že 1. jednoprvkový seznam je uspořádaný;. jsou li A = {a 1,..., a k ) a B = {b 1,..., b k ) uspořádané seznamy, pak lze snadno vytvořit uspořádaný seznam A B tak, že neustále porovnáváme první dva prvky seznamů A a B a menší z nich (v případě rovnosti třeba ten z A) přidáme na poslední místo vytvářeného seznamu A B. Máme li tady za úkol setřídit prvky daného seznamu M, pak seznam rozdělíme na jednoprvkové seznamy. Z jednoprvkových seznamů vytvoříme uspořádané dvouprvkové seznamy (např. tak, že spojujeme první dva seznamy, druhé dva seznamy atd.). Je li počet prvků seznamu M lichý, ponecháme poslední seznam jednoprvkový. Dále z dvouprvkových seznamů vytváříme čtyřprvkové uspořádané seznamy, poslední seznam může mít i méně prvků. Takto postupujeme až dostaneme požadovaný uspořádaný seznam. Ukažme si postup na příkladě seznamu M = {6, 5, 8,, 4, 1,, 7}. V prvním řádku tabulky je seznam, ve druhém řádku je seznam rozdělen na jednoprvkové (již nerozdělitelné) části. Ve třetím řádku jsou uspořádané dvouprvkové seznamy, v čtvrtém řádku jsou čtyřprkové seznamy a v pátém řádku jsou spojeny dva čtyřprkové seznamy; tím je získán požadovaný uspořádaný seznam, který je uveden v posledním řádku. 11 seznam {6, 5, 8,, 4, 1,, 7} jednoprvkové seznamy 6 5 8 4 1 7 dvouprvkové uspořádané seznamy 5 6 8 1 4 7 čtyřprvkové uspořádané seznamy 5 6 8 1 4 7 osmiprvkový uspořádaný seznam 1 4 5 6 7 8 uspořádaný seznam {1,,, 4, 5, 6, 7, 8} Pro úplnost si ukažme, jak vzniká osmiprvkový uspořádaný seznam C (předposlední řádek) sléváním dvou čtyřprvkových uspořádaných seznamů A a B, které jsou v předcházejícím řádku. A 0, 5, 6, 8 B 0 1,, 4, 7 C 0 A 1, 5, 6, 8 B 1, 4, 7 C 1 1 A 5, 6, 8 B, 4, 7 C 1, A 5, 6, 8 B 4, 7 C 1,, A 4 5, 6, 8 B 4 7 C 4 1,,, 4 A 5 6, 8 B 5 7 C 5 1,,, 4, 5 A 6 8 B 6 7 C 6 1,,, 4, 5, 6 A 7 8 B 7 C 7 1,,, 4, 5, 6, 7 A 7 B 7 C 7 1,,, 4, 5, 6, 7, 8 A jaká je složitost uvedeného algoritmu? Nechť má pro jednoduchost výchozí seznam M přesně n = m prvků. Ke spojení dvou k prvkových seznamů je třeba provést přesně k kroků. Celkem je tedy potřeby provést při spojování seznamů m 1 1 (je m 1 dvojic jednoprvkových seznamů) plus m (je m dvojic dvouprvkových seznamů) atd. až plus m 1 (jsou dva m 1 prvkové seznamy) kroků. Pro spojování seznamů je tedy potřeba (m 1) m kroků. Celkem při algoritmu je potřeba provést maximálně

1 m + 1 + (m 1) m kroků. Pro počet potřebných kroků T (n) je T (n) m m. Protože je n = m, je m = log n a tedy pro časová náročnost algoritmu je T (n) O(n log n). Ukažte, že je i T (n) θ(n log n). Třídění haldou Velmi populárnímm algoritmem pro vytváření uspořádaného seznamu čísel z daného seznamu je tzv. metoda třídění haldou. Nejprve si řekněmě co se rozumí pod pojmem halda (anglicky heap). Můžeme si představit, že je to uspořádaná množina s největším prvkem a každý prvek má nějakou číselnou hodnotu. Prvky množiny jsou situovány v k hladinách a splňují následující podmínky: 1. v první hladině je jediný prvek;. v i té hladině, 1 k, je i 1 prvků;. v k té hladině je maximálně k 1 prvků a prvky v hladině jsou umístěny co nejvíce vlevo ; 4. každý prvek v i té hladině, k je pokrýván právě jedním prvkem z hladiny i 1, a to tak, že pokud prvek patří mezi první dva prvky z i té hladiny, je pokrývány prvním prvkem hladiny i 1, pokud prvek patří mezi druhé dva prvky z i té hladiny je pokrývány druhým prvkem hladiny i 1 atd. 5. je li prvek a pokrýván prvkem b, pak hodnota prvku a je větší nebo rovna hodnotě prvku b. Každý prvek haldy, která má k hladin, je možno jednoznačně charakterizovat dvojicí čísel (h, p) (1 h k, 1 p k 1 ) která uvádí, že prvek leží v h té hladině na p tém místě. Každý prvek z h té hladiny (h > 1)je pokrýván právě jedním prvkem z hladiny h 1 (prvkem (h 1, j), jedná li se o prvek (h, j 1) nebo (h, j) a každý prvek (i, j) z i té hladiny pokrývá nejvýše dva prvky, a to prvky (i+1, j 1) (i+1, j) (poslední hladina nemusí být obsazena plně). Každý prvek haldy má tedy přesně jednoho předchůdce (nebo též otce ) a nejvýše dva následníky (nebo též syny ). Hodnota následníka je větší nebo rovna hodnotě předchůdce. Prvek v první hladině se nazývá kořen haldy. Plně obsazená halda, která má k hladin, má přesně 1 + 1 + + + k 1 = k 1 prvků. Na následujícím obrázku jsou zobrazeny příklady hald. 5 9 5 9 5 9 7 8 7 8 10 11 7 8 10 11 Obr. 1: Příklady hald 40 0 0 15 18 Jak je možno z daného seznamu vytvářet haldu? Stačí dodržovat následující dvě pravidla pro přidávání nových prvků do haldy. 1. vytvoříme nový uzel tak, že ho přidáme do poslední hladiny, a to co nejvíce vlevo ;. kontrolujeme, zda je splněno pravidlo hodnota následníka je větší nebo rovna hodnotě předchůdce. Pokud tomu tak není, vyměníme mezi sebou předchůdce a následníka.

V této kontrole pokračuje tak dlouho, až bude mít nově vkládaný prvek hodnotu větší nebo rovnu hodnotě předchůdce nebo až se dostane do kořene haldy. Uvědomme si, že tímto postupen vždy vznikne halda. Vyměníme li totiž mezi sebou předchůdce P a následníka N 1, nic to nemění na požadované relaci mezi případným druhým následníkem N uzlu P a novým předchůdcem uzlu N. Hodnota uzlu N byla větší nebo rovna hodnotě uzlu P a hodnota uzlu P je větší než hodnotu uzlu N 1, tedy určitě je hodnota uzlu N větší než hodnota uzlu N 1. Postup tvorby haldy je ilustrován na následujícím obrázku. 1 5 5 1 1 5 5 5 5 1 1 5 Obr. 1: Tvorba haldy 5 5 7 Určeme složitost algoritmu vytváření haldy. Vložíme li nový prvek do i té hladiny haldy, musíme provést v nejhorším případě i 1 výměn mezi následníkem a předchůdcem. Mějme senam, který má n prvků. Potom existuje číslo k takové, že je n = k 1 + m, kde 0 m < k, tj. halda je tvořena k plně obsazenými hladinami a v poslední hladině je m prvků. Vložení případného prvku do poslední hladiny a následné výměny mezi následníkem a předchůdcem vyžaduje maximálně k kroků. Protože je k n n (pro n ), je k log n = log n. Vkládaní prvků do i té hladiny (s následnými výměnami mezi následníkem a předchůdcem) pro i k vyžaduje méně kroků. Pro počet T (n) případných výměn mezi následníkem a předchůdcem pro vytvoření haldy platí: T (n) n k n log n. Algoritmus vytváření haldy je časové složitosti O(n log n). Nyní si ukažme, jak z haldy vytvořit uspořádaný seznam. Důležité je, že umíme ihned vybrat nejmenší prvek (přesněji jeden z prvků s nejmenší hodnotou). Jedná se vždy o prvek umístěný v kořenu haldy (jediný prvek v první hladině). Haldu budeme rozebírat následujícím algoritmickým postupem: 1. odebereme prvek z kořenu (první hladiny)haldy;. poslední prvek haldy, tj. poslední (zleva do prava) prvek z poslední obsazené hladiny přemístíme do kořenu (první hladiny) haldy;. zajistíme, aby halda splňovala podmínku, že hadnota následníka je větší nebo rovna hodnotě předchůdce. Začneme od kořene a budeme porovnávat hodnoty s následníky. Je li hodnota následníků větší nebo rovna hodnotě předchůdce, je halda v pořádku. V opačném případě zaměníme hodnotu předchůdce s menší z hodnot následníků; jsou li hodnoty obou následníků stejné, provedeme výměnu s následníkem vlevo. 4. kroky 1. až. opakujeme tak dlouho, až rozebereme celou haldu. Z odebíraných prvků vytváříme uspořádaný seznam tak, že prvky vkládáme do vytvářeného uspořádaného seznamu vždy na konec. Je zřejmé, že algoritmus rozebírání halda je opět algoritmem časové složitosti O(n log n). Stejné třídy bude tedy i algoritmus třídění haldou, kterým daný seznam prvků přetvoříme na uspořádaný seznam prvků ve dvou krocích: 1. z daného seznamu vytvoříme haldu;. haldu rozebereme a vytvoříme uspořádaný seznam.

14 Celý postup, tj. oba kroky si ukážeme na jednom příkladě. Výsledky budeme psát do tabulek tak, tak že v řádku tabulky budou stav po provedení příslušného kroku. V řádcích tabulek budou prvky uváděny po hladinách a v hladinách ve stejném pořadí zleva do prava jako v haldě. Zkontrolujte postup pomocí obrázků hald. Máme z daného seznamu {, 5,, 1, 7, 10, 9, 5, 4,, 6} vytvořit uspořádaný seznam. 1. Z daného seznamu vytvoříme haldu. Halda bude mít 4 hladiny, poslední není plně obsazena. hladina 1 4 4 4 4 4 4 pořadí 1 1 1 4 1 4 5 6 vloženo 1. krok. krok 5 5. krok 5 4. krok 5 5. krok 5 1 1 6. krok 1 5 7. krok 1 5 8. krok 1 5 7 7 9. krok 1 5 7 10 10 10. krok 1 5 7 10 9 9 11. krok 1 5 7 10 9 5 5 1. krok 1 5 7 10 9 5 4 4 1. krok 1 4 7 10 9 5 5 14. krok 1 4 7 10 9 5 5 15. krok 1 4 10 9 5 5 7 16. krok 1 4 10 9 5 5 7 6 6 Získaná halda je zobrazena na následujícím obrázku. 1 4 5 5 7 6 10 9 Obr. : Získaná halda

15. Získanou haldu postupně rozebereme. hladina 1 4 4 4 4 4 4 pořadí 1 1 1 4 1 4 5 6 odebráno halda 1 4 10 9 5 5 7 6 1. krok 6 4 10 9 5 5 7 1. krok 6 4 10 9 5 5 7. krok 4 6 10 9 5 5 7 4. krok 7 4 6 10 9 5 5 5. krok 7 4 6 10 9 5 5 6. krok 4 7 6 10 9 5 5 7. krok 4 5 6 10 9 7 5 8. krok 5 4 5 6 10 9 7 9. krok 4 5 5 6 10 9 7 10. krok 7 4 5 5 6 10 9 11. krok 4 7 5 5 6 10 9 1. krok 4 5 5 7 6 10 9 1. krok 9 5 5 7 6 10 4 14. krok 5 9 5 7 6 10 15. krok 5 6 5 7 9 10 16. krok 10 6 5 7 9 5 17. krok 5 6 10 7 9 18. krok 9 6 10 7 5 19. krok 6 9 10 7 19. krok 6 7 10 9 0. krok 9 7 10 6 1. krok 7 9 10. krok 10 9 7. krok 9 10 4. krok 10 9 4. krok 10 Uspořádaný seznam v pořadí odebraných prvků je {1,,,, 4, 5, 5, 6, 7, 9, 10}. Prvočísla Ukažme si další příklady algoritmů, tentokrát z oblasti elementární teorie čísel. Přirozené číslo p se nazývá prvočíslem jesliže čísla 1 a p jsou jediná přirozená čísla, kterými lze dělit číslo p beze zbytku. Přirozené číslo 1 je považováno za prvočíslo. Úloha zní: rozhodněte, zda dané přirozené číslo n je prvočíslo. První a nejjednodušší algoritmus je založen na testování zda je číslo n dělitelné číslem m, m n. Algoritmus je možno formulovat takto: 1. zkusíme, zda je < n. Je li = n algoritmus končí a n je prvočíslo. Je li < n, testujeme zda je n dělitelné číslem. Jestliže ano, n není prvočíslo a algoritmus končí; jestliže ne, přejdeme k dalšímu kroku.. zkusíme, zda je < n. Je li = n algoritmus končí a n je prvočíslo. Je li < n, testujeme zda je n dělitelné číslem. Jestliže ano, n není prvočíslo a algoritmus končí; jestliže ne, přejdeme k dalšímu kroku.

16. takto pokračujeme dále. Algoritmus skončí nejpozději v n-1 krocích. A jak lze tento algoritmus zjednodušit? a) Stačí si například uvědomit, že test zda je n dělitelné číslem i stačí provádět pro i = a dále pouze pro lichá čísla i. b) Další možnost zjednodušení je založena na tom, že pokud je přirozené číslo n dělitelné beze zbytku číslem k {1, n}, pak existuje přirozené číslo m {1, n}, pro které platí n = k m. Předpokládejme, že je k m. Potom je k k k m = n. Tedy je k n. Algoritmus tak může být ukončen mnohem dříve a to testem, zda je i > n. Je li i > n, algoritmus končí konstatováním, že n je prvočíslo. c) Další teoretický výsledek týkající se testování, zda dané číslo je či není prvočíslo, spočívá ve skutečnosti, že pokud n není prvočíslo, pak existuje prvočíslo m, m n, kterým je číslo n dělitelné beze zbytku. Stačí tedy testovat dělitelnost pouze prvočísly, která jsou menší nebo rovna číslu n. To by ovšem znamenalo značnou komplikaci při úloze formulované rozhodněte, zda dané přirozené číslo n je prvočíslo. Zlepšení by to ale přineslo při úloze formulované takto: nalezněte všechna prvočísla, která jsou menší nebo rovna danému číslu n případně při úloze: nalezněte prvních n prvočísel. Samozřejmě tento menší počet nutných testů je komplikován nutností uchovávat již známá prvočísla. Snižuje se časová náročnost algoritmu za cenu zvýšení prostorové náročnosti algoritmu. Poznámka. Pro nalezení všech prvočísel, která jsou menší nebo rovna předem zadanému přirozenému číslu M, existuje jednoduchý algoritmus, který je pojmenován po řeckém matematikovi Eratosthenovi z Kyrény (žil v letech 76194 před n. l.). Algoritmus je v literatuře uváděn jako Eratosthenovo síto. Algoritmus je možno formulovat takto: 0. krok (inicializace algoritmu): vytvoříme množinu všech přirozených čísela dále množinu B = {1}; 1. krok: vezmeme první číslo množiny A, což je číslo. Toto číslo a přesuneme do množiny B a z množiny A odstraníme všechna čísla, která jsou jeho násobkem. Množina A bude obsahovat všechna lichá čísla (A = {, 5, }), která jsou menší nebo rovna číslu M a bude B = {1, }. i tý krok: vezmeme první číslo množiny A. Toto číslo a přesuneme do množiny B a z množiny A odstraníme všechna čísla, která jsou jeho násobkem. Algoritmus končí, jakmile je A = a množina B obsahuje právě všechna prvočísla menší nebo rovna číslu M. V každém kroku je skutečně první číslo množiny A prvočíslem (protože by jinak bylo již odstraněno jako nějaký násobek čísla menšího). Algoritmus by bylo možno také ukončit testem je první číslo množiny A větší než M? Pokud ano, pak jsou již všechna čísla z množiny A prvočísla a je možno je přesunout do množiny B. Ukažme si Eratosthenovo síto na konkrétním příkladě. Nalezněme všechna prvočísla menší nebo rovna číslu 5. 0. krok (inicializace algoritmu): A = {,, 4, 5, 6, 7, 8, 9, 10, 11, 1, 1, 14, 15, 16, 17, 18, 19, 0, 1,,, 4, 5} B = {1}; 1. krok: 5 = 5, A = {, 5, 7, 9, 11, 1, 15, 17, 19, 1,, 5} B = {1, };

. krok: 5 = 5, A = {5, 7, 11, 1, 17, 19,, 5} B = {1,, };. krok: 5 5 = 5 A = {7, 11, 1, 17, 19, } B = {1,,, 5}; 4. krok: protože je 7 > 5 = 5, je A = B = {1,,, 5, 7, 11, 1, 17, 19, }; Všechna prvočísla, která jsou menší nebo rovna číslu 5 jsou: 1,,, 5, 7, 11, 1, 17, 19,. Zápis algoritmu je možno modifikovat tak, že si vytvoříme tabulku všech čísel menších nebo rovno číslu M. Z tabulky postupně odstraňujeme násobky čísel,, 5, 7,.... Tento zápis více připomíná síto. V následujících tabulkách je uveden postup pro hledání všech prvočísel větších rovno a menších než 100. Postupně jsou odstraňovány násobky prvočísel menších než 10 = 100, tj. násobky prvočísel,, 5, 7. V tabulkách jsou označeny tučně. Všechna prvočísla větší než 1, jsou v poslední tabulce. 17 1 4 5 6 7 8 9 10 11 1 1 14 15 16 17 18 19 0 1 4 5 6 7 8 9 0 1 4 5 6 7 8 9 40 41 4 4 44 45 46 47 48 49 50 51 5 5 54 55 56 57 58 59 60 61 6 6 64 65 66 67 68 69 70 71 7 7 74 75 76 77 78 79 80 81 8 8 84 85 86 87 88 89 90 91 9 9 94 95 96 97 98 99 100 1 5 7 9 11 1 15 17 19 1 5 7 9 1 5 7 9 41 4 45 47 49 51 5 55 57 59 61 6 65 67 69 71 7 75 77 79 81 8 85 87 89 91 9 95 97 99 1 5 7 11 1 17 19 5 9 1 5 7 41 4 47 49 5 55 59 61 65 67 71 7 77 79 8 85 89 91 95 97 1 5 7 11 1 17 19 9 1 7 41 4 47 49 5 59 61 67 71 7 77 79 8 89 91 97 1 5 7 11 1 17 19 9 1 7 41 4 47 5 59 61 67 71 7 79 8 89 97

18 Příklady k procvičení 1) Dokažte, že pro funkci f(n) = a 0 n k + a 1 n k 1 + + a 1 n + a k, kde a 0 0, je f(n) = θ(n k ). ) Která z následujících tvrzení jsou platná a která ne. Jednotlivá tvrzení dokažte nebo nalezněte protipříklad. a) je li T (n) = n 5 + n + n, je T (n) O(n 9 ); b) je li T (n) = n 5 + n + n, je T (n) θ(n ); c) je li T (n) = n+, je T (n) O(n ); d) je li T (n) = n, je T (n) O( n ); e) je li T (n) = n, je T (n) O(9 n ); f) je li T (n) = n n, je T (n) O( n ); e) je li T (n) = n, je T (n) O(4 n ); ) Určete typ časové složitosti pro funkci T (n), je li a) T (n) = + 6 + 9 + + n; b) T (n) = 1 + + + + n ; d) T (n) = 1 + + + + n ; d) T (n) = 1 + + + n n ; d) T (n) = n (1 + 1 + 1 1 + 1 + + 1 ); n 4) Danou množinu {6, 8,, 5, 4, 7, 1, 9} přetvořte na uspořádanou množinu metodou: a) přímého vkládání; b) třídění sléváním; d) třídění haldou. Uvádějte všechny elementární kroky. 5) Bez rozkladu na prvočinitele nalezněte největší společné dělitele dvojic čísel: a) 55, 459; b), 459; c), 69; d) 165, 19; e) 85, 145; f) 847, 157; e) 60, 1515; f) 440,1095. 6) Pomocí Hornerova schematu nalezněte zbytek při dělení polynomu f(x) polynomem x a, je li: a) f(x) = x 5 + x 4 + x + x + x + 5, a = ; b) f(x) = x 5 + x 4 + x + x + x + 5, a = ; c) f(x) = x 5 + x 4 + x x + x 5, a = 5; d) f(x) = x 5 + x 4 + x x + x 5, a = ; e) f(x) = x 5 + x 4 x + x + 5x + 7, a = 1; f) f(x) = x 5 + x 4 x + x + 5x + 7, a = 5; g) f(x) = x 5 + x 4 + x + x + 5x + 7, a = 1; h) f(x) = x 5 + x 4 x + x + 5x + 7, a =. 7) Pomocí Hornerova schematu nalezněte hodnoty polynomu f(x) a hodnoty všech derivací polynomu f(x)(až do řádu rovnému stupni polynomu) v daném bodě a, je li: a) f(x) = x 5 + x 4 x + x 5, a = 1; b) f(x) = x 5 + x 4 x + x 5, a = 1; c) f(x) = x 5 + x 4 x + x 5, a = ; d) f(x) = x 4 x + x + 5x, a = 1;

19 e) f(x) = x 4 x + x + 5x, a = ; f) f(x) = x 4 x + x + 5x, a =. Výsledky 5) Výsledky jsou uvedeny v tabulce. 6) Výsledky jsou uvedeny v tabulce. a) b) c) d) e) f) g) h) 51 17 1 51 5 77 45 55 a) b) c) d) e) f) g) h) 58 15 7085 89 7 607 994 7) Výsledky jsou uvedeny v tabulce. a f(a) f (a) f (a) f (a) f (4) (a) f (5) (a) a) 1 1 1 7 19 1 40 b) 1 9 5 8 48 168 40 c) 105 51 460 64 55 40 d) 1 6 1 1 18 4 e) 8 7 4 4 4 e) 94 104 96 66 4