Programování 1. hodina RNDr. Jan Lánský, Ph.D. Katedra informatiky a matematiky Fakulta ekonomických studií Vysoká škola finanční a správní 2015
Vstupní znalosti Podmínky, cykly Funkce, Pole, třídění Retězce Soubory Dvojrozměrná pole, matice Rekurze, zásobník, fronta Backtracking, vlna, heuristiky, ořezávání Jan Lánský Programování 1. hodina 2
Cíle předmětu Programování je o zautomatizování základních postupů. Nutno prakticky trénovat. Ideálně hodinu každý den. Algoritmy pro práci s velkými daty, jejichž přesnou velikost dopředu neznáme Dynamická alokace paměti Spojové seznamy, stromy, grafy Tyto algoritmy zapsat pomocí programu Přednášky budou v C# C# je prostředek, ne cíl Lze pracovat s jiným jazykem Určit časovou a prostorovou složitost použitého algoritmu. Druhý ze čtyř semestrů programování Jan Lánský Programování 1. hodina 3
Cíle hodiny Obecné informace o předmětu Statická a dynamická alokace paměti Operátor new, struktura vs. třída Jednosměrné lineární spojové seznamy Create, ConvertArray, Print InsertToBegin, InsertToEnd InsertBefore, InsertAfter, Find, FindPrevious, Delete Jan Lánský Programování 1. hodina 4
Literatura - C# Předmět učím v C# první rok, takže jsou k dispozici zatím jen slajdy Lze použít literaturu pro Pascal v kombinaci s libovolnou knihou pro C# V.Váňa: Základy programování v C# pro naprosté začátečníky http://www.eamos.cz/amos/kat_inf/externi/kat_inf _03611/files/podklady_pro_cviceni/zacatekcsharp. pdf Jan Lánský Programování 1. hodina 5
Literatura - Pascal P. Töpfer: Programování IS studijní materiály Prg Topfer.pdf Rozsahem téměř odpovídá probíranému učivu P. Kučera: Programování IS studijní materiály Prg Kucera.pdf Nepokrývá celé učivo P.Töpfer: Algoritmy a programovací techniky, Prometheus Praha 1995, 2. vydání 2007 P.Töpfer: Základy programování v úlohách, Scientia Praha 1997 Jan Lánský Programování 1. hodina 6
Příklady není nutné stihnout na hodině, postačí je vypracovat doma a na hodině prezentovat Zápočet 1. podmínka Nutno splnit obě dvě podmínky Splnění povinných příkladů z alespoň 8 z 12 cvičení (z toho splněna cvičení 1, 2, 3 a 5) IS studijní materiály cviceni.doc Vyřešeným příkladům je nutno rozumět, na požádání je mírně modifikovat Vyřešené příklady je nutno prezentovat osobně Prezentování cizích zdrojových kódů jako vlastních Disciplinární řízení Vyloučení ze studia Source code plagiarism may lead to exclusion from the University Исходный код плагиат может привести к исключению из университета Není stanoven žádný termín, do kdy nutno získat zápočet Jan Lánský Programování 1. hodina 7
Nutno splnit obě dvě podmínky Zápočet 2. podmínka Seminární práce 5 až 8 stran na téma z oblasti informatiky nebo matematiky Důraz kladen na práci s literaturou Rešeršní práce, nikoliv vlastní kreativita Vyberte si téma a vedoucího ze seznamu: https://docs.google.com/document/d/1anxeuvluv6oxubdq sathbyek1urlqx3dbpaaby6c2ni/edit?usp=sharing Nejprve si s vedoucím práce domluvte, zda je vybrané téma stále volné. Práce se odevzdává vedoucímu práce, který mě pošle email, že ji schválil. Jan Lánský Programování 1. hodina 8
Vyplatí se studovat poctivě a průběžně Šance na úspěch při studiu obtížnost 1. semestr 2. semestr 3. semestr 4. semestr Poctivec střední těžká velmi těžká střední Podvodník 1 chycen: 1 % 1% nightmare nightmare těžká Podvodník 2 1 % chycen: 0,01 % 1 % 1 % nightmare+ nightmare Podvodník 3 1 % 1 % chycen: 0,0001 % 1 % 1 % 1 % nightmare+ Podvodník 4 1 % 1 % 1 % chycen: 0,000001 % 1 % 1 % 1 % 1 % Šance na výhru ve sportce 0.00001 % cca 10 x vyšší něž Podvodník 4 Jan Lánský Programování 1. hodina 9
Zkouška Zkoušku lze skládat kdykoliv během mojí výuky v semestru (v ZS i LS), není třeba se ohlašovat dopředu, stačí přijít. Libovolný procedurální jazyk Řešení příkladu na papír Není důležitá přesná syntax, ale správné použití řídících konstrukcí Povoleny jen psací potřeby [Nedoporučeno] Zkoušku lze skládat i na PC zadání je obtížnější Povolena jen vestavěná nápověda vývojového prostředí Jan Lánský Programování 1. hodina 10
Zkouška Na známku A je třeba znát i učivo potřebné na známky C a E. Známka E (dobře) Lineární struktury: jednosměrný a obousměrný lineární spojový seznam, zásobník a fronta pomocí seznamů Jeden ze tří: QuickSort, MergeSort, HeapSort Známka C (velmi dobře) Stromové struktury QuickSort, MergeSort, HeapSort Známka A (výborně) Obecné grafy Jan Lánský Programování 1. hodina 11
Statická a dynamická alokace paměti Statická alokace proměnné Proměnné, struktury Hodnota = číslo Statická alokace: na začátku práce známe horní odhad velikost dat se kterými pracujeme Dynamická alokace proměnné Pole, řetězce, třídy Dynamická alokace: složitější práce pro nás i pro překladač. Pro proměnlivé velikosti dat Hodnota = adresa, kde jsou uložena data Reference ref (při volání funkce) Předá se adresa, kde jsou uložena data Jan Lánský Programování 1. hodina 12
Uvolňování paměti Staticky alokovaná paměť automaticky zaniká s koncem funkce, ve které byla alokována Běžné v programovacích jazycích. Garbage collector: dynamicky alokovaná paměť, ke které již nikdo nezná adresu, je po čase prohlášena za uvolněnou paměť. Nemusíme se o ní starat V C a C++ není G.C., musíme se o ní starat Čištění dynamicky alokované paměti proběhne samo od sebe, může nastat v kritickou chvíli, kdy zbrzdí chod programu. Jan Lánský Programování 1. hodina 13
Statická a dynamická alokace Dynamicky alokováno, proto se změní i pole[0] Nová dynamická alokace p, nyní p!= pole Změna jen p[0], ale ne pole[0] Změna jen x, ale ne i. Změna y a j (reference) Předávání j referencí Statická alokace i, j Dynamická alokace Nová dynamická alokace, stará data zahozena Jan Lánský Programování 1. hodina 14
Překladač si pamatuje (datový typ), zda v proměnné je číselná hodnota nebo adresa Velmi zjednodušený model paměti i j po le Jak vypadá paměť I. [0] [1] 2 3 500??? 0 0??????? 52 56 60 64 68 72 500 508 Hodnotou proměnná i (na adrese 52) je číslo 2 Hodnotou proměnná j (na adrese 56) je číslo 3 Hodnotou proměnná pole (na adrese 60) je adresa 500, kde se nachází pole dvou celých čísel (pole[0] adresa 500, pole[1] adresa 504) Operátor new alokace a vynulování paměti Jan Lánský Programování 1. hodina 15
i j po le Jak vypadá paměť II. [0] [1] [2] 2 3 508????? 0 0 0???? 52 56 60 64 68 72 508 520 Paměť na adresách 500 a 504 se stane nedostupnou. Hodnotou proměnná pole (na adrese 60) je adresa 508, kde se nachází pole tří celých čísel (pole[0] adresa 508, pole[1] adresa 512, pole[2] adresa 516) Jan Lánský Programování 1. hodina 16
i j po le Jak vypadá paměť III. p x y [0] [1] [2] 2 3 508 508 2 56?? 0 0 0???? 52 56 60 64 68 72 508 520 Volání funkce: Hodnotou parametru p (na adrese 64) je adresa 508 (okopírovaná hodnota proměnné pole) Hodnotou parametru x (na adrese 68) je číslo 2 (okopírovaná hodnota proměnné i) Hodnotou parametru y (na adrese 72) je adresa 56 (adresa proměnné j), protože parametr y je předávaný referencí. Při použití parametru y se pracuje s číselnou hodnotou uloženou na adrese 56 (aktuálně 3). Jan Lánský Programování 1. hodina 17
i j po le Jak vypadá paměť IV. p x y [0] [1] [2] [0] [1] [2] [3] 2 3 508 520 2 56?? 6 0 0 7 0 0 0 52 56 60 64 68 72 508 520 Hodnotou parametru p (na adrese 64) je adresa paměti 508, do buňky paměti na této adrese s indexem 0 (= 508+4*0) zapíšeme hodnotu 6 Provedeme novou dynamickou alokaci. Hodnotou parametru p (na adrese 64) je adresa 520, kde se nachází pole 4 celých čísel (adresy 520, 524, 528 a 532). Paměť na adrese 508 je nadále dostupná z proměnné pole. Hodnotou parametru p (na adrese 64) je adresa paměti 520, do buňky paměti na této adrese s indexem 0 (=520+4*0) zapíšeme hodnotu 7 Jan Lánský Programování 1. hodina 18
i j po le Jak vypadá paměť V. p x y [0] [1] [2] [0] [1] [2] [3] 2 5 508 520 4 56?? 6 0 0 7 0 0 0 52 56 60 64 68 72 508 520 Hodnotou parametru x (na adrese 68) se stává číslo 4 Hodnotou parametru y (adresa 72) je adresa 54. Paměť na adrese 56 (proměnná j) přepíšeme hodnotou 5. Jan Lánský Programování 1. hodina 19
i j po le Jak vypadá paměť VI. p x y [0] [1] [2] 2 5 508????? 6 0 0???? 52 56 60 64 68 72 508 520 Skončení běhu funkce: Parametry funkce p (adresa 64), x (adresa 68) a y (adresa 72) se stanou nedostupnými. Hodnotou parametru y (adresa 72) byla adresa 520. Paměť na této adrese se stane také nedostupnou (adresa této paměti není uložena v žádné jiné proměnné. Efekt funkce: Po skončení funkce dojde pouze k jediné změně paměti oproti stavu před jejím spuštěním: příkaz p[0] = 6 přepsal paměť na adrese 508 hodnotou 6. Adresa 508 odpovídá pole[0] Jan Lánský Programování 1. hodina 20
Struktura vs. třída Z hlediska OOP je rozdílů více, popisujeme jen ty, které se týkají alokace paměti Struktura (struct) Vždy statická alokace (i za použití new) Proměnná obsahuje hodnotu Třída (class) Vždy dynamická alokace Proměnná obsahuje adresu Neformálně řečeno: Třída je referencí na strukturu Speciální hodnota null (obdoba číselné hodnoty 0) Umožňuje rekurzivně obsahovat datové položky té samé třídy Jan Lánský Programování 1. hodina 21
Struktura vs. třída Obě struktury s1 i s2 mají hodnoty {0,0} Třídu c1 nejde inicializovat po částech Parametr typu třída se chová jako reference na strukturu Hodnota c2.x se změní na 3 Hodnota s2.x zůstává 0 Nulový odkaz null: adresa paměti, ze které je zakázáno číst hodnoty i zapisovat do ní hodnoty. Můžeme se ale ptát, zda adresa je null. Jan Lánský Programování 1. hodina 22
Překladač si pamatuje (datový typ), zda v proměnné je číselná hodnota nebo adresa Velmi zjednodušený model paměti s1.x s1.y Jak vypadá paměť s2.x s2.y c1 c2 s.x s.y c.x.y 0 0 0 0 null 500 2 0 500 3 0???? 52 56 60 64 68 72 76 80 84 500 508 Formální parametr s (adresa 76) je struktura, proto se změna neprojeví na skutečném parametru s2 (adresa 60) Formální parametr c (adresa 84) je třída. Jeho hodnotou je adresa 500. Tato hodnota je shodná s hodnotou skutečného parametru c2 (adresa 72). Změna se projeví na adrese 500, na kterou odkazují c i c2. Proto c2.x má hodnotu 3 Jan Lánský Programování 1. hodina 23
Jednosměrný lineární spojový seznam Lidově: (jednosměrný) spoják AJ: (Singly) linked list Datová struktura, který umožňuje uchovat dopředu neznámý počet prvků daného datového typu Dvě datové položky (data) a [odkaz na] následující prvek (next) = následník daného prvku Konec seznamu next = null Vkládání a mazání prvků na libovolné místo Při znalosti předchůdce (nebo trikem) v čase O(1) Bez znalosti předchůdce O(n) Vkládání za prvek v čase O(1) Vyhledání prvku v čase O(n) Jan Lánský Programování 1. hodina 24
Spojový seznam vs. pole Seznam Dopředu neznámý počet prvků, který se může měnit Hledání prvku podle klíče O(n) Mazání, Přidávání prvků O(1) Pole Při znalosti předchůdce nebo trikem Dopředu známý počet prvků (nebo jeho horní odhad). Přímý přístup k prvku pomocí indexu O(1) Mazání, přidávání prvků O(n) Jan Lánský Programování 1. hodina 25
Jednosměrný lineární spojový seznam Musí být class Datová položka: libovolný datový typ i struktura Následník prvku konec seznamu: next = null Prázdný seznam: Seznam s = null Vytvoříme 3 prvky s daty 1, 2, 3 Z prvního prvku přes dvojité použití next získám hodnotu třetího prvku. Prvky napojíme na sebe: 1->2->3->null Jan Lánský Programování 1. hodina 26
Překladač si pamatuje (datový typ), zda v proměnné je číselná hodnota nebo adresa Velmi zjednodušený model paměti Jak vypadá paměť s1 s2 s3.d.n.d.n.d.n 500 508 516 1 508 2 516 3 null?????? 52 56 60 500 508 516 524 Proměnné s1 (adresa 52), s2 (adresa 56) a s3 (adresa 60) jsou třídy. Jejich hodnoty jsou adresy 500, 508 a 516. Položka data proměnné s1 se nachází na adrese 500 a má hodnotu 1. Položka next proměnné s1 se nachází na adrese 504 a její hodnotou je adresa 508 (hodnota proměnné s2). Analogicky pro s2 a s3. Jan Lánský Programování 1. hodina 27
Grafické znázornění s1.next s1.next.next s1 s2 s3 data 1 2 3 next null s1.next.next. data Jan Lánský Programování 1. hodina 28
Postup implementace funkce Nakreslíme si obrázek spojového seznamu V obrázku naznačíme změny odkazů, které má funkce provést. Určíme pořadí těchto změn. Prvky seznamu, se kterými pracujeme si označíme proměnnými Změny odkazů z obrázku přepíšeme do zdrojových kódů funkce. Zohledníme pravidla pro práci se seznamy (null hodnoty, první a poslední prvek) (Obvykle) průchod spojovým seznamem Jan Lánský Programování 1. hodina 29
Pravidla pro práci se seznamy Zamyslet se, zda v dané funkci jsou tato ošetření třeba Ošetřovat parametry Prázdný seznam (null) Jednoprvkový seznam Ošetřovat speciální pozice v seznamu První prvek Poslední prvek Návratová hodnota Prázdný seznam (null) Když se může změnit začátek seznamu funkce musí v návratové hodnotě vracet začátek seznamu Jan Lánský Programování 1. hodina 30
Průchod spojovým seznamem Při průchodu spojovým seznamem potřebujeme proměnnou, která uchovává právě procházený prvek Doporučuji ve všech funkcích mít speciální proměnnou pro průchod, která bude vždy pojmenována stejně V přednáškách proměnná pro průchod "akt" V některých funkcích takto budeme mít řádek navíc Vyhneme se ale případným chybám u funkcí, které potřebují uchovávat začátek seznamu. Jan Lánský Programování 1. hodina 31
Print Výpis na obrazovku Pomocí while cyklu Aktuálně zpracovávaný prvek nastavíme na začátek seznamu Dokud je aktuální prvek různý od null vypíšeme ho na obrazovku Posun na následující prvek Pomocí for cyklu Řídící proměnná cyklu je aktuální prvek seznamu Jan Lánský Programování 1. hodina 32
Print: grafické znázornění akt = s akt!= null akt = akt.next akt!= null akt = akt.next akt!= null akt = akt.next akt == null data 1 2 3 next null Jan Lánský Programování 1. hodina 33
Create, ConvertArray V C# je next nastaven na null automaticky, ale zvyk pro jiné jazyky Vytvoříme jednoprvkový seznam pro zadanou hodnotu Ukončení seznamu: Následníka prvku nastavíme na null. Z pole vyrobíme seznam. Použití při testování funkcí Proměnná vys uchovává začátek seznamu Proměnná akt udržuje aktuální konec seznamu Proměnná tmp: z prvku pole jsme vytvořili jednoprvkový seznam Zda přidáváme do seznamu první prvek nebo nějaký jiný. Přidávaný prvek napojíme na konec seznamu Jan Lánský Programování 1. hodina 34
Find Najití první výskytu prvku se zadanou hodnotou. Čas: O(n) Podobné jako funkce print Místo výpisu prvku na obrazovku testujeme, zda se jeho data rovnají hledané hodnotě. V případě nalezení hledaného prvku funkce končí a vrací nalezený prvek. Posun na následující prvek Nebyl nalezen žádný prvek s požadovanou hodnotou Jan Lánský Programování 1. hodina 35
InsertToBegin InsertToEnd Vložení hodnoty na začátek seznamu. Čas O(1) Vložení hodnoty na konec seznamu. Čas O(n) Vytvoříme jednoprvkový seznam pro zadanou hodnotu a za tento nový seznam připojíme původní seznam. Vracíme nový začátek seznamu. Vracíme začátek původního seznamu Nový jednoprvkový seznam připojíme na konec seznamu Původní seznam byl prázdný, vracíme nový jednoprvkový seznam Hledáme konec seznamu, tj. prvek, který má následníka null Jan Lánský Programování 1. hodina 36
InsertToBegin a InsertToEnd: grafické znázornění tmp InsertToBegin: tmp.next = s; InsertToEnd: akt.next = tmp; data 4 5 tmp next null s akt akt akt data 1 2 3 next null Jan Lánský Programování 1. hodina 37
InsertAfter Vložení hodnoty do seznamu za zadaný prvek "kam". Čas: O(1) Pokud je seznam prázdný nebo prvek, za který mám vkládat je prázdný, vkládám na konec seznamu Vracíme začátek původního seznamu Nutno v tomto pořadí: 1. Nově vytvořený prvek bude mít stejného následníka jakého má prvek "kam". 2. Následníkem prvku kam bude nově vytvořený prvek. Jan Lánský Programování 1. hodina 38
InsertAfter: grafické znázornění Vložení prvku s hodnotou 5 za prvek s hodnotou 2 Nutno dodržet pořadí kroků 1 a 2 tmp data 2) kam.next = tmp 5 next 1) tmp.next = kam.next s kam data 1 2 3 next null Jan Lánský Programování 1. hodina 39
FindPrevious Nalezení prvku, který předchází zadému prvku "s2". Čas: O(n) Prázdný seznam nebo prázdný zadaný prvek nebo zadaný prvek je prvním prvkem seznamu Dokud aktuální prvek není poslední v seznamu Pokud po aktuálním prvku následuje zadaný prvek, vracíme aktuální prvek Zadaný prvek není v seznamu Posun na následující prvek Jan Lánský Programování 1. hodina 40
FindPrevious: grafické znázornění Hledáme předchůdce prvku s2 s hodnotou 3 akt = s akt.next!= null akt.next!= s2 akt.next!= null akt.next!= s2 akt.next!= null akt.next == s2 return akt akt.next == null data 1 2 3 next null Kdybychom bývali nenalezli hledaný prvek, cyklus by zde skončil Jan Lánský Programování 1. hodina 41
Vložení hodnoty do seznamu před zadaný prvek". Čas: O(n) InsertBefore Varianta Trick má čas O(1) ale lze ji použít jen pokud na prvky seznamu nemám žádné další odkazy odjinud. Doporučuji nepoužívat Najdeme předchůdce, pokud neexistuje vkládáme na začátek seznamu. 1. Následníkem nově vytvořeného prvku "tmp" bude prvek "kam". 2. Následníkem předchůdce prvku "kam" bude prvek "tmp". Trik: (1) Do nově vytvářeného prvku "tmp" zkopírujeme data prvku "kam". (2) Následníkem prvku "tmp" bude následník prvku "kam". (3) Následníkem prvku "kam" bude prvek "tmp". (4) Data prvku "kam" budou data, která vkládáme Jan Lánský Programování 1. hodina 42
Delete Smazání zadaného prvku. Čas: O(n) Najdeme předchůdce. Vracíme začátek seznamu Předchůdce mazaného prvku bude ukazovat na následníka mazaného prvku Prázdný seznam nebo prázdný zadaný prvek Prázdný předchůdce, mažeme první prvek seznamu vracíme druhý prvek seznamu Varianta Trick má čas O(1) mažeme následující prvek, podobný princip jako u InsertBefore. Nejde takto mazat poslední prvek Jan Lánský Programování 1. hodina 43
Mažeme prvek "co" s hodnotou 2 Delete: grafické znázornění s prev co prev.next co.next data 1 2 3 next null "co" už není v seznamu, garbage collector ho časem odstraní Jan Lánský Programování 1. hodina 44
Funkce modifikující seznam Návratovou hodnotou funkcí Insert a Delete je nový spojový seznam, který vznikne modifikací původního spojového seznamu Proměnnou, která uchovává původní spojový seznam nelze dále využívat, respektive při jejím využívání můžeme způsobit chyby programu Původní seznam nahradíme novým seznamem Jan Lánský Programování 1. hodina 45
Funkce modifikující seznam Místo využití návratové hodnoty by šlo psát funkce tak, aby vstupní spojový seznam se předával referencí Tato varianta je možná, ale obtížnější z programátorského hlediska Při předčasném ukončení funkce místo příkazu s return musí být často složený příkaz obsahující přiřazení do původního seznamu a po něm následuje příkaz s return. V jazyku C vede k dvojnásobným ukazatelům (odkazům) Jan Lánský Programování 1. hodina 46
Zpětná vazba Objevili jste ve slajdech chyby? Včetně pravopisných Nechápete nějaký slajd? Je příliš obtížný, nesrozumitelný? Máte nějaký nápad na vylepšení? Anonymní formulář Odeslání za pár vteřin http://goo.gl/forms/wjx99cbyy9 Jan Lánský Programování 1. hodina 47