Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
statnice:bakalar:b0b36prp [2025/05/11 12:59] – external edit 127.0.0.1 | statnice:bakalar:b0b36prp [2025/05/11 15:17] (current) – external edit 127.0.0.1 | ||
---|---|---|---|
Line 19: | Line 19: | ||
## Řídicí struktura | ## Řídicí struktura | ||
- | Řídicí | + | Řídicí |
- | Tři základní druhy: | + | - **Sekvenční struktura** – příkazy se vykonávají |
- | - **Posloupnost** – příkazy se vykonávají | + | - **Větvení** – `if`, `if...else`, |
- | - **Větvení** – rozhodování na základě podmínky (if, switch). | + | - **Cykly** – `for` (pokud známe počet opakování), `while`, `do...while` (provádí tělo alespoň jednou). |
- | - **Cyklus** – opakování příkazů dokud je splněna podmínka (for, while, do-while). | + | |
Příklad větvení: | Příklad větvení: | ||
Line 97: | Line 96: | ||
- Vícenásobné změny hodnoty proměnné v jediném výrazu (např. `a = a++ + ++a`) | - Vícenásobné změny hodnoty proměnné v jediném výrazu (např. `a = a++ + ++a`) | ||
- | Jazyk C umí využít nedefinované chování k optimalizaci kódu, protože kompilátor může předpokládat, | + | Jazyk C umí využít nedefinované chování k optimalizaci kódu, protože kompilátor může předpokládat, |
+ | Například pokud přičteme k signed integeru 1 a poté v podmínce zkontrolujeme, | ||
+ | Například u přetečení `signed int` může kompilátor předpokládat, | ||
- | ## Coding style | + | ## Coding style a čitelnost |
- | Kódovací styl je způsob, jakým je kód napsán. Existuje mnoho různých stylů, ale většina z nich se snaží o to, aby byl kód čitelný a srozumitelný. Například: | + | Kódovací styl je způsob, jakým je kód napsán. Existuje mnoho různých stylů, ale většina z nich se snaží o to, aby byl kód čitelný a srozumitelný. |
+ | |||
+ | Například: | ||
- Používat mezery mezi operátory a operandami | - Používat mezery mezi operátory a operandami | ||
- Používat odsazení pro bloky kódu | - Používat odsazení pro bloky kódu | ||
Line 112: | Line 115: | ||
Srozumitelnost kódu je důležitá, | Srozumitelnost kódu je důležitá, | ||
- | </ | ||
- | ===== 2. Dekompozice programu | + | # 2. Dekompozice programu |
- | < | ||
Dekompozice je proces ve kterém se komplexní kus logiky programu rozdělí na menší části pro lepší čitelnost. Většinou se jedná o rozdělení programu do jednotlivých funkcí, rozdělení do více souborů atd... | Dekompozice je proces ve kterém se komplexní kus logiky programu rozdělí na menší části pro lepší čitelnost. Většinou se jedná o rozdělení programu do jednotlivých funkcí, rozdělení do více souborů atd... | ||
Line 174: | Line 175: | ||
### Funkce s argumenty | ### Funkce s argumenty | ||
Obecně funkce s argumenty vypadá: | Obecně funkce s argumenty vypadá: | ||
- | ```C | + | ```c |
return_type function_name(arg1, | return_type function_name(arg1, | ||
{ | { | ||
Line 204: | Line 205: | ||
return n * factorial(n - 1); // rekurzivní volání | return n * factorial(n - 1); // rekurzivní volání | ||
} | } | ||
+ | ``` | ||
- | </ | + | # 3. Datové typy |
- | + | ||
- | ===== 2. Datové typy ===== | + | |
- | + | ||
- | < | + | |
Datové typy v C jsou: | Datové typy v C jsou: | ||
Line 215: | Line 213: | ||
- char | - char | ||
- int | - int | ||
+ | - short | ||
- long | - long | ||
- long long | - long long | ||
Line 227: | Line 226: | ||
char b = ' | char b = ' | ||
``` | ``` | ||
+ | |||
+ | proměnné dále můžou mít modifikátory jako: | ||
+ | - `signed` - má jak kladné tak záporné hodnoty | ||
+ | - `unsigned` - má pouze kladné hodnoty | ||
+ | - `static` - hodnota se uchovává mezi voláním funkce, je uložena ve static data | ||
+ | - `const` - hodnota se nemění | ||
+ | - `volatile` - hodnota se může měnit mimo program (např. hardware) | ||
+ | - `extern` - proměnná je definována v jiném souboru | ||
+ | |||
+ | V C není datový typ string. Textové řetězce se reprezentují jako pole znaků zakončené `\0`. | ||
+ | |||
+ | ```c | ||
+ | char text[] = " | ||
+ | char *text2 = " | ||
+ | ``` | ||
+ | |||
+ | pozor na rozdíl mezi `const int *` - konstantní hodnota, `const int * const` - konstantní pointer na konstantní hodnotu, a `int * const` - konstantní pointer na proměnnou, v C lze ale vše přetypovat, | ||
+ | - konstantní pointer nelze přesměrovat na jinou proměnnou, ale hodnota na kterou ukazuje se může měnit | ||
+ | - konstantní hodnota se nemění, ale pointer se může přesměrovat na jinou proměnnou | ||
+ | - konstantní pointer na konstantní hodnotu se nemění, ani hodnota na kterou ukazuje | ||
můžeme includovat knihovnu `inttypes.h` která nám umožní používat typy se specifickou velikostí, jako například `uint8_t`, pro 8 bit unsigned integer. | můžeme includovat knihovnu `inttypes.h` která nám umožní používat typy se specifickou velikostí, jako například `uint8_t`, pro 8 bit unsigned integer. | ||
Line 248: | Line 267: | ||
datový typ `void*` je speciální typ, který může ukazovat na jakýkoli typ dat. | datový typ `void*` je speciální typ, který může ukazovat na jakýkoli typ dat. | ||
- | # Pole, ukazatel, textový řetězec | + | # 4. Pole, ukazatel, textový řetězec |
Pole v C můžeme definovat dvěma způsoby, statické pole: | Pole v C můžeme definovat dvěma způsoby, statické pole: | ||
Line 272: | Line 291: | ||
``` | ``` | ||
takto vytvořené pole je umístěno na haldě, pro získání místa na haldě musíme o místo zažádat pomocí `malloc` a pak je správné ho na konci uvolnit pomocí `free`. | takto vytvořené pole je umístěno na haldě, pro získání místa na haldě musíme o místo zažádat pomocí `malloc` a pak je správné ho na konci uvolnit pomocí `free`. | ||
+ | void* je speciální ukazatel, který může ukazovat na libovolný typ dat a je běžně používán pro obecné funkce pracující s různými datovými typy. | ||
- | # Zpracování vstupů a ošetření chybových stavů | + | # 5. Zpracování vstupů a ošetření chybových stavů |
Můžeme použít funkce `scanf`, `fscanf` a podobné. | Můžeme použít funkce `scanf`, `fscanf` a podobné. | ||
Line 294: | Line 314: | ||
``` | ``` | ||
- | # Zápis, překlad a spouštění programu v C | + | # 6. Zápis, překlad a spouštění programu v C |
Soubory píšeme do souborů s příponom `.c` a knihovny do `.h`, includování probíhá pomocí makra `#include`. | Soubory píšeme do souborů s příponom `.c` a knihovny do `.h`, includování probíhá pomocí makra `#include`. | ||
Line 301: | Line 321: | ||
- *Preprocesor*: | - *Preprocesor*: | ||
o `.i` souborů | o `.i` souborů | ||
- | - *Kompilátor*: | + | - *Kompilátor*: |
- | - objetové soubory se slnkují do spustitelného souboru | + | |
+ | - *Linker*: objektové soubory se slinkují (přeloží se adresy pro volání funkcí, nastavuje enviroment pro předávání argumentů, atd...) do spustitelného souboru | ||
- | soubor lze zkompilovat se statickými (`#include " | ||
+ | Soubor lze zkompilovat se statickými (`#include " | ||
- | # Abstraktní datové typy (ADT) | + | Spuštění souboru nezačíná ve funkci `main` ale ve funkci `_start`, která připraví prostředí pro spuštění programu a zavolá funkci main. Funkce main pak vrací hodnotu, která se předává operačnímu systému |
+ | jako návratová hodnota programu. | ||
- | Abstraktní datové typy jsou přístup k programování | + | # 7. Abstraktní datové typy (ADT) |
+ | |||
+ | Abstraktní datové typy (ADT) představují konceptuální model datových struktur, | ||
## Příklad | ## Příklad | ||
Line 328: | Line 351: | ||
K tomuto interfacu existuje poté specifická implementace. Která může vypadat takhle: | K tomuto interfacu existuje poté specifická implementace. Která může vypadat takhle: | ||
- | ```C | + | ```c |
struct Stack { size_t top, cap; int *buf; }; | struct Stack { size_t top, cap; int *buf; }; | ||
Line 366: | Line 389: | ||
``` | ``` | ||
- | # Jednosměrný a obousměrný spojový seznam | + | # 8. Jednosměrný a obousměrný spojový seznam |
+ | |||
+ | ## Spojové seznamy | ||
+ | |||
+ | Dynamická struktura, kde každý prvek obsahuje hodnotu a odkaz na další prvek. | ||
+ | |||
+ | - **Jednosměrný** – každý prvek ukazuje na následující. | ||
+ | - **Obousměrný** – prvky obsahují odkazy na předchozí i následující prvek. | ||
+ | - **Kruhový** – poslední prvek ukazuje zpět na první. | ||
+ | |||
+ | Výhoda: **flexibilní velikost**. Nevýhoda: **vyšší paměťová režie** | ||
Může být jednoduše naimplementován pomocí dvou struktur, node: | Může být jednoduše naimplementován pomocí dvou struktur, node: | ||
Line 400: | Line 433: | ||
v normálním spojovém seznamu má poslední prvek hodnotu next NULL, v obousměrném má head-> | v normálním spojovém seznamu má poslední prvek hodnotu next NULL, v obousměrném má head-> | ||
- | # Nelineární spojové struktury | + | |
+ | # 9. Nelineární spojové struktury | ||
+ | |||
+ | ## Stromy – základní pojmy | ||
+ | |||
+ | - **Cesta** – posloupnost uzlů od kořene k uzlu. | ||
+ | - **Délka cesty** – počet hran mezi kořenem a uzlem. | ||
+ | - **Hloubka uzlu** – délka cesty od kořene. | ||
+ | - **Výška stromu** – maximální hloubka uzlu ve stromu. | ||
+ | - **Šířka stromu** – počet uzlů na stejné úrovni. | ||
+ | - **Vyvážený strom** – uzly rovnoměrně rozložené, | ||
+ | |||
+ | Příklad uzlu v C: | ||
+ | ```c | ||
+ | typedef struct Node { | ||
+ | int data; | ||
+ | struct Node* left; | ||
+ | struct Node* right; | ||
+ | } Node; | ||
+ | ``` | ||
Například strom: | Například strom: | ||
Line 416: | Line 468: | ||
``` | ``` | ||
- | # Datové struktury reprezentovatelné polem | + | ## Typy stromů |
- | # Využití prioritní fronty | + | ### Uspořádaný strom |
+ | - Potomci každého uzlu jsou uspořádáni (například podle klíče). | ||
+ | ### Neuspořádaný strom | ||
+ | - Čistě strukturální strom, pořadí potomků není určeno. | ||
+ | ## Binární vyhledávací strom (BST) | ||
+ | - Každý uzel má maximálně 2 potomky (levý a pravý podstrom). | ||
+ | - Levý potomek obsahuje menší hodnotu, pravý potomek větší hodnotu než rodič. | ||
+ | - Slouží k rychlému vyhledávání, | ||
+ | - Implementace je většinou rekurzivní. | ||
+ | - Základní typy: | ||
+ | - **Plný binární strom** – všechny listy na stejné hloubce. | ||
+ | - **Úplný binární strom** – každý vnitřní uzel má dva potomky. | ||
+ | - **Vyvážený binární strom** – hloubka listů se liší maximálně o 1. | ||
+ | ### Matematické vlastnosti | ||
+ | - Počet uzlů: `n` | ||
+ | - Hloubka stromu: `h` | ||
+ | - Minimální počet uzlů: `n = 2h + 1` | ||
+ | - Maximální počet uzlů: `n = 2(h+1) - 1` | ||
+ | - Počet listů: `ceil(n/2)` | ||
+ | ## Implementace binárního stromu v C | ||
+ | ```c | ||
+ | typedef struct node { | ||
+ | int value; | ||
+ | struct node *left; | ||
+ | struct node *right; | ||
+ | } node_t; | ||
+ | node_t *tree = NULL; | ||
+ | ``` | ||
+ | ## Procházení stromu | ||
+ | ### BFS (do šířky) | ||
+ | - Prochází se úrovně stromu po vrstvách. | ||
+ | ### DFS (do hloubky) | ||
+ | - Existují 3 základní metody: | ||
+ | - **Preorder** | ||
+ | ```c | ||
+ | void preorder(node_t *root) { | ||
+ | if (root) { | ||
+ | printf(" | ||
+ | preorder(root-> | ||
+ | preorder(root-> | ||
+ | } | ||
+ | } | ||
+ | ``` | ||
+ | - **Inorder** | ||
+ | ```c | ||
+ | void inorder(node_t *root) { | ||
+ | if (root) { | ||
+ | inorder(root-> | ||
+ | printf(" | ||
+ | inorder(root-> | ||
+ | } | ||
+ | } | ||
+ | ``` | ||
+ | - **Postorder** | ||
+ | ```c | ||
+ | void postorder(node_t *root) { | ||
+ | if (root) { | ||
+ | postorder(root-> | ||
+ | postorder(root-> | ||
+ | printf(" | ||
+ | } | ||
+ | } | ||
+ | ``` | ||
+ | ## Vyhledávání v binárním vyhledávacím stromu (BST) | ||
+ | ```c | ||
+ | node_t* search(node_t* root, int key) { | ||
+ | if (!root || root-> | ||
+ | return root; | ||
+ | if (key < root-> | ||
+ | return search(root-> | ||
+ | else | ||
+ | return search(root-> | ||
+ | } | ||
+ | ``` | ||
+ | # 10. Datové struktury reprezentovatelné polem | ||
+ | ## Zásobník (Stack) | ||
+ | Zásobník je lineární datová struktura pracující na principu **LIFO (Last In, First Out)** – poslední prvek vložený do zásobníku je první, který se odebere. | ||
+ | ### Základní operace: | ||
+ | - **push**: vloží prvek na vrchol zásobníku. | ||
+ | - **pop**: odebere a vrátí prvek z vrcholu zásobníku. | ||
+ | - **peek** (top): vrátí hodnotu vrcholu zásobníku, | ||
+ | - **isEmpty**: | ||
+ | Zásobník lze implementovat pomocí pole nebo spojového seznamu. Používá se například při rekurzi, parsování výrazů nebo při realizaci funkcí volání v programech. | ||
+ | ## Fronta (Queue) | ||
+ | |||
+ | Fronta je lineární datová struktura pracující na principu **FIFO (First In, First Out)** – první prvek vložený do fronty je první, který se odebere. | ||
+ | |||
+ | ### Základní operace: | ||
+ | - **enqueue**: | ||
+ | - **dequeue**: | ||
+ | - **peek** (front): vrátí hodnotu na čele fronty, aniž by ji odebral. | ||
+ | - **isEmpty**: | ||
+ | |||
+ | Fronta se používá například při plánování procesů, správě úloh, nebo v simulacích, | ||
+ | |||
+ | ## Prioritní fronta – spojový seznam nebo pole | ||
+ | - Každý prvek má přiřazenou prioritu. Při vybírání se vždy vybere prvek s nejvyšší nebo nejnižší prioritou (dle implementace). | ||
+ | - Prioritní frontu lze implementovat jako: | ||
+ | - **spojový seznam** (pomalé vybírání O(n), rychlé vkládání O(1)), | ||
+ | - **pole** (pomalé vybírání O(n)), | ||
+ | - **haldu (heap)** (rychlé vybírání i vkládání O(log n)). | ||
+ | |||
+ | Příklad struktury polem: | ||
+ | ```c | ||
+ | typedef struct { | ||
+ | void **queue; | ||
+ | int *priorities; | ||
+ | int count; | ||
+ | int head; | ||
+ | int tail; | ||
+ | } queue_t; | ||
+ | ``` | ||
+ | |||
+ | ## Halda (heap) | ||
+ | - Binární plný strom s vlastností haldy: | ||
+ | - Rodič ≤ potomci (min-heap) nebo rodič ≥ potomci (max-heap). | ||
+ | - Prvky jsou uloženy v poli. | ||
+ | |||
+ | ### Indexování: | ||
+ | - levý potomek: $2\cdot i + 1$ | ||
+ | - pravý potomek: $2\cdot i + 2$ | ||
+ | - rodič: $(i - 1) / 2$ | ||
+ | |||
+ | ### Základní operace haldy | ||
+ | |||
+ | #### Insert / Push | ||
+ | - Přidá prvek na konec pole (na první volné místo). | ||
+ | - Prvek se **" | ||
+ | - Složitost: **O(log n)**. | ||
+ | |||
+ | #### Pop | ||
+ | - Odebere prvek z kořene (index 0 = minimum/ | ||
+ | - Poslední prvek se přesune na kořen a **" | ||
+ | - Složitost: **O(log n)**. | ||
+ | |||
+ | #### Peek | ||
+ | - Vrátí hodnotu na kořeni (nejmenší / největší prvek podle typu haldy), aniž by prvek odstranila. | ||
+ | - Složitost: **O(1)**. | ||
+ | |||
+ | ### Výhody haldy | ||
+ | - V porovnání s prostou prioritní frontou v poli má halda efektivní složitost operací. | ||
+ | - Halda je ideální pro implementaci **prioritní fronty**, například pro algoritmy hledání nejkratší cesty (Dijkstra, A*). | ||
+ | |||
+ | # 11. Využití prioritní fronty – hledání nejkratší cesty v grafu | ||
+ | |||
+ | ## Dijkstrův algoritmus | ||
+ | 1. Nastavíme vzdálenosti všech uzlů na nekonečno (`INT_MAX`), | ||
+ | 2. Vložíme startovací uzel do prioritní fronty (haldy). | ||
+ | 3. Dokud fronta není prázdná: | ||
+ | - Vybereme uzel s nejmenší vzdáleností. | ||
+ | - Aktualizujeme vzdálenosti sousedů. | ||
+ | - Přidáme sousedy do fronty, pokud se vzdálenost zmenšila. | ||
+ | |||
+ | Příklad: | ||
+ | ```c | ||
+ | typedef struct { | ||
+ | int vertex; | ||
+ | int distance; | ||
+ | } PriorityQueueNode; | ||
+ | ``` | ||
+ | |||
+ | Složitost: $O((V + E) \cdot log V)$ | ||
+ | Dijkstra algoritmus předpokládá, | ||
+ | ## A* algoritmus | ||
+ | - Modifikace Dijkstra s heuristikou (odhadem vzdálenosti do cíle). | ||
+ | - Heuristika snižuje počet prozkoumaných uzlů → rychlejší hledání. | ||
+ | - Nejčastější použití v herní AI, robotice, mapových aplikacích. | ||
</ | </ |