zpracovana cast s kontejnery
This commit is contained in:
@@ -82,19 +82,135 @@ Poznámka: Příklady jsou zjednodušené a ne vždy jsou 100% syntakticky práv
|
||||
### Co je pravidlo tří (rule of three)?
|
||||
### Jaký je tvar definice lambda funkce v C++? Uveďte příklad a popište, co funkce dělá.
|
||||
# STL kontejnery
|
||||
## 1) Co je to kontejner?
|
||||
## 2) Jaký je rozdíl mezi sekvenčními a asociativními kontejnery? Uveďte příklad.
|
||||
## 3) Jaké jsou klíčové vlastnosti kontejneru std::vector?
|
||||
## Jaké jsou klíčové vlastnosti kontejneru std::map?
|
||||
## Jaké jsou klíčové vlastnosti kontejneru std::list?
|
||||
## Jakého datového typu může být klíč kontejneru std::map?
|
||||
## Co je třeba zajistit v případě, že klíčem v kontejneru std::map je strukturovaný datový typ (např. naše vlastní třída)?
|
||||
## Jaký je význam datového typu std::pair?
|
||||
## Co je to iterátor? Uveďte příklad.
|
||||
## Jaký je rozdíl mezi konstantním a nekonstantním iterátorem?
|
||||
## Co všechno je třeba zajistit pro vytvoření vlastního iterátoru?
|
||||
## Co je range-for cyklus? Uveďte příklad.
|
||||
## Uveďte příklad použití algoritmu sort (deklarujte vektor libovolného datového typu, vložte do něj data a vektor seřaďte).
|
||||
### 1) Co je to kontejner?
|
||||
Kontejnery jsou datové struktury určené k ukládání kolekce dat (hodnot) a k manipulaci s nimi. Například to je `vector`, který funguje jako dynamické pole.
|
||||
|
||||
Máme různé typy kontejnerů - sekvenční asociativní (a pak údajně neseřazený asociativní a adaptery pro jiné ovládání existujících kontejnerů, ale to raději neřešme). Viz. další otázka.
|
||||
|
||||
Hlavní smysl kontejnerů je ulehčit práci při programovaní. Je to často již implementované řešení, které se v kódu jednoduše používá, nebo je to rada, jak si takové řešení udělat. Je to vrstva abstrakce.
|
||||
### 2) Jaký je rozdíl mezi sekvenčními a asociativními kontejnery? Uveďte příklad.
|
||||
**Sekvenční kontejnery** pracují s daty nezávisle na jejich hodnotě. To je míněno tak, že třeba data ukládají dle pořadí, ve kterém do kontejneru přišli a data mají unikátní index. Je to například `std::vector` a `std::list`
|
||||
|
||||
**Asociativní kontejnery** řeší data většinou dle nějakého klíče, který je k nim přiřazen. Například `std::map`. Data jsou pak seřazena tak, aby bylo například efektivní vyhledávání a místo indexu mají právě na vyhledání klíč.
|
||||
- `std::map` - data seřazeny dle porovnávací funkce
|
||||
- `std::unordered_map` - data neseřazeny a hledány dle jejich hashe
|
||||
### 3) Jaké jsou klíčové vlastnosti kontejneru std::vector?
|
||||
**Vector** je prakticky **dynamické** **pole** s podobnými vlastnostmi jako jeho implementace v C++, akorát to celé někdo implementoval v třídě s funkcemi za nás.
|
||||
- Data jsou seřazeny za sebou dle jejich velikosti v paměti. (tedy 5 prvek int o velikosty 4 byty je na 17-20 bytu)
|
||||
- Vyhledávání konkrétního prvku je O(1) -> dopočítám hned z velikosti a pozice
|
||||
- přidání/odstranění na konec - O(1)
|
||||
- Odstranění a přidání je kamkoli - O(n) -> vyžaduje přesun všech prvků v poli
|
||||
- pole má hodnotu velikosti (kolik zabírá bytů prvky) a kapacity (kolik bytů si dynamicky rezervuje). Kapacita musí být větší než velikost, jinak je třeba přealokovat
|
||||
- adresy prvků nejsou stabilní kvůli realokaci
|
||||
|
||||
`std::vector<int> kontejner1`;
|
||||
### 4) Jaké jsou klíčové vlastnosti kontejneru std::map?
|
||||
Ukládá si pro každý prvek 2 hodnoty a to **klíč a hodnotu**. Všechny prvky jsou seřazené podle klíče a jeho porovnávací funkce, který zajišťuje operace o O(log n). Seřazení může třeba být binární strom.
|
||||
|
||||
Kontejner umožňuje vymyslet a vložit vlastní porovnávací funkci v šabloně.
|
||||
### 5) Jaké jsou klíčové vlastnosti kontejneru std::list?
|
||||
List je kontejner, který vlastně není moc odlišný od toho, co by člověk čekl (pokud si to pamatuje).
|
||||
Data jsou uložena každá ve vlastní buňce v paměti. Každá buňka umožňuje přístup k dalšímu a předchozímu prvku (pamatuji se jejich ukazatele).
|
||||
|
||||
- proto je každá buňka bezpečně samostatně uložena v paměti nezávisle na ostatních buňkách
|
||||
- Je jednoduché přidávat/odebírat na známé pozice prvky - O(1) -> stačí změnit ukazatele v buňkách předchozí a další buňky (říká se tomu často uzel).
|
||||
- Hledání prvku na n-té pozice je obtížné, je třeba projít všechny prvky, které k němu vedou - O(n)
|
||||
|
||||
- vhodné pro potřebu čistého rychléhi přidávání a mazaání prvků, ale nevhodné pro rychlý náhodný přístup
|
||||
|
||||
`std::list<int> L;`
|
||||
### 6) Jakého datového typu může být klíč kontejneru std::map?
|
||||
Klíč `std::map` může být kteréhokoli typu, který je možná porovnávat pomocí řazení (má operátor `>` a `<`). Nebo je možné dodat vlastní porovnávací funkci (komparátor).
|
||||
### 7) Co je třeba zajistit v případě, že klíčem v kontejneru std::map je strukturovaný datový typ (např. naše vlastní třída)?
|
||||
- buď je třeba zajistit, aby objekty třídy byly porovnatelné pomocí `>` a `<` například pomocí přetěžování operátorů
|
||||
- nebo je možné sepsat vlastní comparator (vlastní porovnávací funkci)
|
||||
### 8) Jaký je význam datového typu std::pair?
|
||||
`std::pair` je datový typ, který umí ukládat 2 prvky libovolného typu
|
||||
|
||||
```cpp
|
||||
pair<int, string> p = {1, "ahoj"};
|
||||
p.first = 7;
|
||||
p.second = "krkavců";
|
||||
```
|
||||
|
||||
vhodné je se i podívat na operaci vzájemného porovnávání párů
|
||||
### 9) Co je to iterátor? Uveďte příklad.
|
||||
Iterátor je třída, která je spojená s určitým kontejnerem. Úkol prvků této třídy je jednoduchý a to umožnění jednoduché procházení prvky kontejneru.
|
||||
|
||||
Iterátor by tedy měl být dereferencovatelný -> dereferencí `*it` získáme hodnotu nynějšího prvku, jako by to byl ukazatel. Dále přičtením `++it` získáme další prvek kontejneru. Iterátoru přiřadíme hodnotu pomocí funkcá `.begin()` -> hodnota prvního iterátoru, a zjišťujeme konec kontejneru pomocí `.end()`.
|
||||
|
||||
Příklad:
|
||||
```cpp
|
||||
std::vector<int> pole = {1, 2, 3};
|
||||
std::vector<int>::iterator it = pole.begin();
|
||||
|
||||
for(std::vector<int>::iterator it = pole.begin(); it != pole.end(); ++i)
|
||||
{
|
||||
std::cout << *it << std::endl;
|
||||
}
|
||||
```
|
||||
### 10) Jaký je rozdíl mezi konstantním a nekonstantním iterátorem?
|
||||
- Pomocí **nekontantního** iterátoru můžu měnit hodnotu prvku, na který ukazuje.
|
||||
- Hodnotu prvku na který ukazuje **konstantní** iterátor měnit nemůžu.
|
||||
- Potřebuji změnit typ iterátoru a také používám speciální funkci
|
||||
|
||||
```cpp
|
||||
std::vector<int> pole = {1, 2, 3};
|
||||
std::vector<int>::iterator it = pole.begin();
|
||||
std::vector<int>::const_iterator cit = pole.cbegin(); //vlastni funkce
|
||||
|
||||
*it = 10; //můžu
|
||||
*cit = 20; //nesmim, je to const...
|
||||
```
|
||||
|
||||
### 11) Co všechno je třeba zajistit pro vytvoření vlastního iterátoru?
|
||||
- iterátor musí mít dereferenci -> lze získat hodnotu jeho prvku
|
||||
- lze přičítat takto `++it`
|
||||
- lze odčítat takto `--it'
|
||||
- lze porovnávat `==` a `!=` -> hlavně pro `.begin()` a `.end()`
|
||||
|
||||
zbytek podle kontejneru a kontextu (a podle toho, jak je vlastně vůbec myšlena tato otázka)
|
||||
- je třeba mít `end` a `begin`, konstruktor u kontejneru etc...
|
||||
### 12) Co je range-for cyklus? Uveďte příklad.
|
||||
Je to specifický zápis `for` loop, který umžňuje iterovat všemi prvkami kontejneru.
|
||||
|
||||
```cpp
|
||||
std::vector<int> pole = {1, 2, 3};
|
||||
|
||||
for (auto &i : pole)
|
||||
{
|
||||
i++;
|
||||
}
|
||||
```
|
||||
|
||||
V tomto kódu se projedou všehny hodnoty vektoru a přičte se k ním jedna.
|
||||
`for (auto &i : pole)` -> napravo je název pole, nalevo je hodnotu prvku, používá se auto s referencí, aby se fyzicky nekopíroval každý prvek a bylo to nezávislé na typu.
|
||||
|
||||
prvek `i` pak reprezentuje aktuálně prvek iterace, tedy nabere hodnotu každého prvku pole
|
||||
|
||||
**Obdobně lze udělat loop i pro iteraci listem**.
|
||||
### 13) Uveďte příklad použití algoritmu sort (deklarujte vektor libovolného datového typu, vložte do něj data a vektor seřaďte).
|
||||
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
int main() {
|
||||
std::vector<int> v = {5, 2, 9, 1, 7};
|
||||
std::sort(v.begin(), v.end());
|
||||
for (const auto& x : v)
|
||||
{
|
||||
std::cout << x << " ";
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Sort porovná prvky podle jejich operárů `<` a `>`, funguje univerzálně u všech typů, pokud mají porovnávání definované.
|
||||
|
||||
U stringů to třeba porovnává lexikograficky.
|
||||
Jinak je třeba definovat `>` `<` pomocí přetěžování operátorů a nebo dodat vlastní porovnávací funkci. -> `std::sort(v.begin(), v.end(), comparator)` -> kde comparator je porovnávací funkce
|
||||
# Praktické programování (Qt a související)
|
||||
- Co je to event-driven programování?
|
||||
- Jaký je rozdíl mezi událostí a signálem?
|
||||
|
||||
Reference in New Issue
Block a user