VŠFS B_Prg Programování: Sbírka příkladů na cvičení RNDr. Jan Lánský, Ph.D. Příklady jsou rozděleny do jednotlivých hodin. Každý příklad má stanovený počet bodů za správné řešení. Ke splnění hodiny je třeba získat alespoň 10 bodů. K zisku zápočtu je třeba splnit alespoň 6 z 12 cvičení a zároveň musí být splněna cvičení 1, 2, 3 a 5. K zisku zápočtu je rovněž nutno vypracovat a odevzdat seminární práci (podrobné zadání) na téma z oblasti informatiky nebo matematiky. Příklady je nutno prezentovat osobně (v čase cvičení, případně jindy po domluvě). Prezentování cizích zdrojových kódů jako vlastních povede k zahájení disciplinárního řízení a může vést až k vyloučení ze studia. Objevili jste v příkladech chybu (i pravopisnou)? Je nějaký příklad nesrozumitelný? Je nějaký příklad příliš těžký, lehký vzhledem k počtu bodů? Máte nápady na nové příklady? Dejte mě vědět, zabere Vám to pár vteřin: http://goo.gl/forms/wJX99cbyy9
Nejúspěšnější řešitelé (maximum bodů je 394) 1. Student – školní rok – počet bodů 2. Student – školní rok – počet bodů 3. Student – školní rok – počet bodů 4. Student – školní rok – počet bodů 5. Student – školní rok – počet bodů 6. Student – školní rok – počet bodů 7. Student – školní rok – počet bodů 8. Student – školní rok – počet bodů 9. Student – školní rok – počet bodů 10. Student – školní rok – počet bodů
1. hodina Příklady vyřešte v libovolném procedurálním programovacím jazyce. Správnost programu otestujte zadáním různých vstupních hodnot. Hodina se považuje za splněnou po zisku alespoň 10 bodů z možných 31 bodů. Příklad 1.1: Funkce pro práci s jednosměrným spojovým seznamem celých čísel. Následující funkce napište s optimálním počtem průchodů spojovým seznamem: a) Napište funkci, která uloží spojový seznam do textového souboru. [1 bod] b) Napište funkci, která načte z textového souboru spojový seznam, který byl uložen pomocí funkce z příkladu 1.1a. [1 bod] c) Napište funkci, která vrátí počet výskytů zadaného prvku ve spojovém seznamu. [1 bod] d) Napište funkci, která ze spojového seznamu odstraní poslední z prvků, jejichž hodnota je shodná se zadanou hodnotou. [2 body] e) Napište funkci, která ze spojového seznamu odstraní prvek s nejvyšší hodnotou. Pokud má více prvků stejnou hodnotu, odstraní první z nich. [2 body] f) Napište funkci, která obrátí pořadí prvků ve spojovém seznamu (za použití jednoho průchodu spojovým seznamem). [3 body] g) Napište funkci, prvky spojového seznamu uspořádá sestupně. [3 body] h) Napište funkci, která ve spojovém seznamu prohodí (pomocí odkazů, nikoliv výměnou hodnot) první prvek a poslední prvek. [2 body] i) Napište funkci, která ve spojovém seznamu prohodí (pomocí odkazů, nikoliv výměnou hodnot) druhý prvek a předposlední prvek. Poznámka: V případě spojového seznamu o dvou prvcích je předposledním prvkem první prvek a druhým prvkem poslední prvek, dojde tedy k jejich výměně. Při testování vyzkoušejte funkci pro seznam se 4 prvky. [3 body] Ukázka: int[] pole = { 1055, 2, 29, 8, 7, 15, 29, 8, 22, 6, 29 }; Seznam s1 = ConvertArray(pole); // 1055->2->29->8->7->15->29->8->22->6->29 Save("spojak.txt", s1); // 1055 2 29 8 7 15 29 8 22 6 29 Seznam s2 = Load("spojak.txt"); // 1055->2->29->8->7->15->29->8->22->6->29 int pocet = Count(s1, 29); // 3 s1 = DeleteLast(s1, 8); // 1055->2->29->8->7->15->29->22->6->29 s1 = DeleteMax(s1); // 2->29->8->7->15->29->22->6->29 s1 = Reverse(s1); // 29->6->22->29->15->7->8->29->2 s1 = Sort(s1); // 29->29->29->22->15->8->7->6->2 s1 = SwapFirstLast(s1); // 2->29->29->22->15->8->7->6->29 s1 = SwapSecondPrenultimate(s1); // 2->6->29->22->15->8->7->29->29
Příklad 1.2: Funkce pro práci se dvěmi jednosměrnými spojovými seznamy celých čísel. Následující funkce napište s s optimálním počtem průchodů spojovým seznamem: a) Napište funkci, která lexikograficky porovná dva spojové seznamy. Návratové hodnoty funkce budou -1, 0 a 1. [1 bod] b) Napište funkci, která vytvoří nový spojový seznam jako kopii existujícího spojového seznamu. Po modifikaci jednoho ze seznamů se neprojeví změny v druhém seznamu. [1 bod] c) Napište funkci, která z jednoho spojového seznamu vytvoří dva spojové seznamy. Liché prvky vstupního seznamu se stanou prvky prvního výstupního spojového seznamu, sudé prvky se stanou prvky druhého výstupního spojového seznamu. [3 body] d) Napište funkci, která spojí dva spojové seznamy do jednoho. Prvky jednotlivých vstupních seznamů se budou ve výstupním seznamu pravidelně střídat. Pokud je jeden ze vstupních seznamů kratší, po vyčerpání jeho prvků následují ve výstupním spojovém seznamu pouze prvky druhého spojového seznamu. [3 body] Ukázka: int[] p1 = { 15, 6, 19, 25, 7, 0, 6, 1, 85 }; int[] p2 = { 15, 6, 8, 66, 2, 3 }; Seznam s1 = ConvertArray(p1); // 15->6->19->25->7->0->6->1->85 Seznam s2 = ConvertArray(p2); // 15->6->8->66->2->3 int i = Compare(s1, s2); // 1 Seznam s3 = Copy(s1); // 15->6->19->25->7->0->6->1->85 Seznam s4 = null, s5 = null; Split(s1, ref s4, ref s5); // 15->19->7->6->85 a 6->25->0->1 Seznam s6 = Merge(s4, s5); // 15->6->19->25->7->0->6->1->85 Příklad 1.3: Dlouhá celá čísla pomocí spojových seznamů Napište následující funkce pro práci s dlouhými celými čísly, které používají způsob uložení cifer little endian pro vnitřní reprezentaci a big endian pro vnější reprezentaci. a) Napište funkci, která ze zadaného textového řetězce vytvoří dlouhé celé číslo. Číslo je v textovém řetězci zapsané pomocí způsobu uložení cifer big endian [1 bod] b) Napište funkci, která zadané dlouhé celé číslo převede na textový řetězec za použití způsobu uložení cifer big endian. [1 bod] c) Napište funkci, která sečte dvě dlouhá celá čísla [3 body] Ukázka: string string Seznam Seznam Seznam string
c1 c2 s1 s2 s3 c3
= = = = = =
"1762569"; "9500954"; ConvertString(c1); // 9->6->5->2->6->7->1 ConvertString(c2); // 4->5->9->0->0->5->9 Sum(s1, s2); // 3->2->5->3->6->2->1->1 ToString(s3); // "11263523";
2. hodina Příklady vyřešte v libovolném procedurálním programovacím jazyce. Správnost programu otestujte zadáním různých vstupních hodnot. Hodina se považuje za splněnou po zisku alespoň 10 bodů z možných 33 bodů. Příklad 2.1: Fronta pomocí jednosměrného spojového seznamu Implementujte datovou strukturu fronta za použití jednosměrného lineárního spojového seznamu. Napište funkce Create, Enqueue, Dequeue, Front, IsEmpty a Vypis. [5 bodů] Ukázka: Fronta f = Create(); Enqueue(f, 4); Enqueue(f, 1); Enqueue(f, 8); int i1 = Dequeue(f); // 4 int i2 = Dequeue(f); // 1 int i3 = Front(f); // 8 bool b = IsEmpty(f); // false Enqueue(f, 5); Enqueue(f, 7); Vypis(f); // 8 5 7 Příklad 2.2: Cyklický obousměrný spojový seznam Implementujte následující funkce pro práci s cyklickým obousměrným spojovým seznamem: a) Funkce Vypis vypíše seznam na obrazovku. [1 bod] b) Funkce Find vrátí první nalezený prvek seznamu obsahující hledanou hodnotu. [1 bod] c) Funkce InsertAfter vloží do seznamu nový prvek se zadanou hodnotou. [3 body] d) Funkce Delete smaže ze seznamu zadaný prvek. [3 body] Ukázka: Seznam2C s = null; s = InsertAfter(s, 5); Vypis(s); // 5 s = InsertAfter(s, 7); Vypis(s); // 5 7 s = InsertAfter(s, 2); Vypis(s); // 5 2 7 InsertAfter(s.next, 1); // neukladame novy zacatek Vypis(s); // 5 2 1 7 s = InsertAfter(s.next, 9); Vypis(s); // 2 9 1 7 5 Delete(s.next); // neukladame novy zacatek Vypis(s); // 2 1 7 5 Seznam2C s2 = Find(s, 7); s = Delete(s2); Vypis(s); // 5 2 1
Příklad 2.3: Funkce pro práci obousměrným spojovým seznamem celých čísel. a) Napište funkci, která ze spojového seznamu odstraní všechny prvky, jejichž hodnota je shodná se zadanou hodnotou. [3 body] b) Napište funkci, která obrátí pořadí prvků ve spojovém seznamu (za použití jednoho průchodu spojovým seznamem). [3 body] c) Napište funkci, prvky spojového seznamu uspořádá vzestupně [3 body] d) Napište funkci, která ve spojovém seznamu prohodí (pomocí odkazů, nikoliv výměnou hodnot) první prvek a poslední prvek. [2 body] e) Napište funkci, která ve spojovém seznamu prohodí (pomocí odkazů, nikoliv výměnou hodnot) druhý prvek a předposlední prvek. Poznámka: V případě spojového seznamu o dvou prvcích je předposledním prvkem první prvek a druhým prvkem poslední prvek, dojde tedy k jejich výměně. Při testování vyzkoušejte funkci pro seznam se 4 prvky. [3 body] Ukázka: int[] pole = { 1055, 2, 29, 8, 7, 15, 29, 8, 22, 6, 29 }; Seznam s1 = ConvertArray(pole); // 1055<->2<->29<->8<->7<->15<->29<->8<->22<->6<->29 s1 = DeleteAll(s1, 29); // 1055<->2<->8<->7<->15<->8<->22<->6 s1 = Reverse(s1); // 6<->22<->8<->15<->7<->8<->2<->1055 s1 = Sort(s1); // 2<->6<->7<->8<->8<->15<->22<->1055 s1 = SwapFirstLast(s1); // 1055<->6<->7<->8<->8<->15<->22<->2 s1 = SwapSecondPrenultimate(s1); // 1055<->22<->7<->8<->8<->15<->6<->2 Příklad 2.4: Funkce pro práci se dvěmi obousměrnými spojovými seznamy celých čísel. Následující funkce napište s s optimálním počtem průchodů spojovým seznamem: a) Napište funkci, která z jednoho spojového seznamu vytvoří dva spojové seznamy. Liché prvky vstupního seznamu se stanou prvky prvního výstupního spojového seznamu, sudé prvky se stanou prvky druhého výstupního spojového seznamu. [3 body] b) Napište funkci, která spojí dva spojové seznamy do jednoho. Prvky jednotlivých vstupních seznamů se budou ve výstupním seznamu pravidelně střídat. Pokud je jeden ze vstupních seznamů kratší, po vyčerpání jeho prvků následují ve výstupním spojovém seznamu pouze prvky druhého spojového seznamu [3 body] Ukázka: int[] p1 = { 15, 6, 8, 66, 2 }; Seznam2 s1 = ConvertArray(p1); // 15<->6<->8<->66<->2 Seznam2 s2 = null, s3 = null; Split(s1, ref s2, ref s3); // 15<->8<->2 a 6<->66 Seznam2 s4 = Merge(s2, s3); // 15<->6<->8<->66<->2
3. hodina Příklady vyřešte v libovolném procedurálním programovacím jazyce. Správnost programu otestujte zadáním různých vstupních hodnot. Hodina se považuje za splněnou po zisku alespoň 10 bodů z možných 38 bodů. Příklad 3.1: Binární vyhledávací strom na papír Na papír si napište 20 různých celých čísel (jiných než vaši spolužáci). Čísla by měla být pokud možno náhodná (a nesetříděná). a) Na papír nakreslete binární vyhledávací strom, který vznikne postupným přidáváním těchto čísel do prázdného stromu. Na pokyn vyučujícího do stromu rovněž vložte další číslo, nebo čísla, která Vám vyučující zadá. [2 body] b) Nakreslete nový binární vyhledávací strom, který vznikne ze stromu z bodu (a) smazáním uzlu, který má dva syny. Tímto způsobem smažte tři uzly (vzniknou tři stromy). Na pokyn vyučujícího rovněž smažte další uzel nebo uzly, který Vám vyučující zadá. [3 body] Příklad 3.2: Binární vyhledávací strom a) Napište funkci, která pro zadaný uzel binárního stromu vrátí jeho strýce. [2 body] b) Napište funkci, která pro zadaný uzel vypíše celou cestu od kořene k tomuto uzlu. [2 body] c) Napište rekurzivní funkci, která pro zadaný uzel spočte počet uzlů ve stromu, jehož je tento uzel kořenem [2 body] d) Napište funkci Insert, která do binárního vyhledávacího stromu vloží prvek se zadanou hodnotou. Příklad byl předveden na přednášce, proto není hodnocen. [0 bodů] e) Napište funkci Delete, která z binárního vyhledávacího stromu odstraní uzel, jehož hodnota se rovná zadané hodnotě. [5 bodů] f) Napište funkci DeleteAbove, která z binárního vyhledávacího stromu odstraní všechny uzly s hodnotou vyšší než je zadaná hodnota. [5 bodů] g) Napište funkci, která vypíše binární vyhledávací strom jako sestupně setříděnou posloupnost hodnot jeho uzlů. [3 body] Příklad 3.3: Dokonale vyvážený strom Napište funkci, která z hodnot prvků zadaných v poli vytvoří dokonale vyvážený binární vyhledávací strom. [4 body] Příklad 3.4: AVL strom Napište funkci, která provede vložení prvku do AVL stromu, využijte obrázky rotací ve výukových materiálech, na které je uveden odkaz v přednášce. [10 bodů]
4. hodina Příklady vyřešte v libovolném procedurálním programovacím jazyce. Správnost programu otestujte zadáním různých vstupních hodnot. Hodina se považuje za splněnou po zisku alespoň 10 bodů z možných 48 bodů. Příklad 4.1: Stromy a) Napište rekurzivní funkci, která z obecného stromu odstraní všechny listy. [2 body] b) Napište nerekurzivní funkci, která z obecného stromu odstraní všechny listy. [3 body] c) Napište nerekurzivní funkci, který do souboru vypíše prvky binárního vyhledávacího stromu setříděné vzestupně [3 body]. d) Napište funkci, která do souboru vypíše prvky binárního stromu setříděné dle jejich vzdálenosti od kořene (měřené počtem uzlů na cestě od kořene k danému uzlu). Pro každý uzel uveďte i jeho vzdálenost. [3 body]. Příklad 4.2: Nejčastější slova Napište funkci, která v zadaném textovém souboru najde zadaný počet nejčastěji se vyskytujících slov. Tato najitá slova včetně počtu jejich výskytů budou vypsány na obrazovku sestupně dle počtu výskytů. Pokud má několik slov stejný počet výskytů, budou vypsána rovněž všechna slova, která mají stejný počet výskytů jako slovo, které se umístilo na posledním místě, které je ještě vypisováno. [10 bodů] Příklad 4.3: Aritmetický výraz a) Napište funkci, která zadaný textový řetězec vyhodnotí jako celočíselný aritmetický výraz. Povolený jsou závorky, unární operátory + a -, binární operátory +, -, *, /, funkce abs (absolutní hodnota), sgn (signum). [6 bodů] b) Funkce bude navíc umět vyhodnotit dvojparametrické funkce nsn (nejmenší společný násobe) a nsd (největší společný dělitel) [4 body] c) Funkce bude navíc umět vyhodnotit funkce min a max, které mohou mít proměnlivý počet parametrů (2 a více). [4 body] d) Funkce bude navíc umět vyhodnotit posfitxní operátor faktoriálu !. [3 body] Příklad 4.4: Vlastní příklad na obecné stromy Najděte vhodná přirozená data, která lze reprezentovat pomocí obecného stromu. Data by měla být vytvořena pouze za účelem tohoto příkladu. Doporučené formáty jsou xml a jeho varianty (např. docx), txt. Napište funkci, která zadaný soubor převede do podoby obecného stromu. Tento strom v lidsky čitelné podobě vypište na obrazovku. [10 bodů]
5. hodina Příklady vyřešte v libovolném procedurálním programovacím jazyce. Správnost programu otestujte zadáním různých vstupních hodnot. Hodina se považuje za splněnou po zisku alespoň 10 bodů z možných 24 bodů. Příklad 5.1: Třídící algoritmy na papír Na papír si napište 20 různých celých čísel (jiných než vaši spolužáci). Čísla by měla být pokud možno náhodná (a nesetříděná). a) Na papíru předveďte vzestupné setřídění čísel pomocí algoritmu Quicksort. [3 body] b) Na papír předveďte vzestupné setřídění čísel pomocí algoritmu Merge sort. [3 body] Příklad 5.2: Třídící algoritmy Napište následující třídící algoritmy pro sestupné setřídění zadaného vstupního pole: a) Rekurzivní Quicksort [4 body] b) Rekurzivní Merge sort [4 body] c) Nerekurzivní Quicksort [5 bodů] d) Nerekurzivní Merge sort [5 bodů]
6. hodina Příklady vyřešte v libovolném procedurálním programovacím jazyce. Správnost programu otestujte zadáním různých vstupních hodnot. Hodina se považuje za splněnou po zisku alespoň 10 bodů z možných 29 bodů. Příklad 6.1: Třídící algoritmy na papír Na papír si napište 20 různých celých čísel (jiných než vaši spolužáci). Čísla by měla být pokud možno náhodná (a nesetříděná). a) Na papíru předveďte sestupné setřídění čísel pomocí algoritmu heapsort implementovaného pomocí dynamické alokace paměti [3 body] b) Na papír předveďte sestupné setřídění čísel pomocí algoritmu heapsort implementovaného pomocí pole. [3 body] Příklad 6.2: Třídící algoritmy Napište následující třídící algoritmy pro sestupné setřídění zadaného vstupního pole: a) heapsort implementovaný pomocí dynamické alokace paměti [4 body] b) heapsort implementovaný pomocí pole [4 body] Příklad 6.3: Vnější třídění Naprogramujte vnější třídění souboru a) pomocí algoritmu merge (pozor neplést s merge sortem) [5 bodů] b) s využitím předtřídění pomocí haldy [5 bodů] c) s využitím předtřídění pomocí haldy a stupně slučování K [5 bodů]
7. hodina Příklady vyřešte v libovolném procedurálním programovacím jazyce. Správnost programu otestujte zadáním různých vstupních hodnot. Hodina se považuje za splněnou po zisku alespoň 10 bodů z možných 31 bodů. Příklad 7.1: B-stromy na papír Na papír si napište 20 různých celých čísel (jiných než vaši spolužáci). Čísla by měla být pokud možno náhodná (a nesetříděná). a) Na papír nakreslete B-strom, který vznikne postupným přidáváním těchto čísel do prázdného stromu. Na pokyn vyučujícího do stromu rovněž vložte další číslo, nebo čísla, která Vám vyučující zadá. [3 body] b) Nakreslete nový B-strom, který vznikne ze stromu z bodu (a) smazáním prvku. Tímto způsobem smažte tři prvky(vzniknou tři stromy). Prvky zvolte tak, aby při mazání došlo k zajímavým situacím. Na pokyn vyučujícího rovněž smažte další prvek nebo prvky, který Vám vyučující zadá. [3 body] Příklad 7.2: Trie na papír Na papír si napište 20 různých textových řetězců (jiných než vaši spolužáci). Čísla by měla být pokud možno náhodná (a nesetříděná). a) Na papír nakreslete trii, který vznikne postupným přidáváním těchto řetězců do prázdné trie. Na pokyn vyučujícího do trie rovněž vložte další číslo, nebo čísla, která Vám vyučující zadá. [2 body] b) Nakreslete novou trii, který vznikne z trie z bodu (a) odebráním jedné hodnoty. Tímto způsobem odeberte tři hodnoty (vzniknou tři trie). Odebírané hodnoty zvolte tak, aby při odebírání došlo k zajímavým situacím. Na pokyn vyučujícího rovněž odeberte další hodnotu nebo hodnoty, které Vám vyučující zadá. [3 body] Příklad 7.3: B-stromy Napište algoritmy pro práci s datovou strukturou B-stromu a) Find [2 body] b) Insert [4 body] c) Delete [5 bodů] Příklad 7.4: Trie Napište algoritmy pro práci s datovou strukturou trie a) Find [2 body] b) Insert [3 body] c) Delete [4 bodů]