btreemap and hashset
This commit is contained in:
276
priprava/rust_priprava5.md
Normal file
276
priprava/rust_priprava5.md
Normal file
@@ -0,0 +1,276 @@
|
||||
# BTreeMap — krok za krokom
|
||||
|
||||
Každá kapitola: prečítaj, pozri príklady, urob úlohy. Až potom choď ďalej.
|
||||
|
||||
```rust
|
||||
use std::collections::BTreeMap; // toto treba vždy
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Kapitola 1: Čo to je a rozdiel oproti HashMap
|
||||
|
||||
BTreeMap je to isté ako HashMap — kľúč → hodnota — ale s jedným veľkým rozdielom: **kľúče sú vždy zoradené**.
|
||||
|
||||
| | HashMap | BTreeMap |
|
||||
|-|---------|----------|
|
||||
| Poradie kľúčov | náhodné | zoradené (od najmenšieho) |
|
||||
| Rýchlosť | O(1) | O(log n) |
|
||||
| Kedy použiť | väčšinou | keď potrebuješ zoradené kľúče |
|
||||
| Import | `use std::collections::HashMap` | `use std::collections::BTreeMap` |
|
||||
|
||||
```rust
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
let mut mapa = BTreeMap::new();
|
||||
mapa.insert("Cyril".to_string(), 22);
|
||||
mapa.insert("Anna".to_string(), 25);
|
||||
mapa.insert("Boris".to_string(), 30);
|
||||
|
||||
// Iterácia — kľúče SÚ zoradené abecedne!
|
||||
for (meno, vek) in &mapa {
|
||||
println!("{}: {}", meno, vek);
|
||||
}
|
||||
// Anna: 25
|
||||
// Boris: 30
|
||||
// Cyril: 22
|
||||
```
|
||||
|
||||
S HashMap by poradie bolo náhodné. S BTreeMap je vždy zoradené.
|
||||
|
||||
Pre čísla zoradí od najmenšieho:
|
||||
```rust
|
||||
let mut mapa = BTreeMap::new();
|
||||
mapa.insert(3, "tri");
|
||||
mapa.insert(1, "jedna");
|
||||
mapa.insert(2, "dva");
|
||||
|
||||
for (k, v) in &mapa {
|
||||
println!("{}: {}", k, v);
|
||||
}
|
||||
// 1: jedna
|
||||
// 2: dva
|
||||
// 3: tri
|
||||
```
|
||||
|
||||
### Úlohy 1
|
||||
|
||||
**1a.** Vytvor BTreeMap s 5 menami (String) a vekmi (u32). Vypíš ich. Over, že sú zoradené abecedne.
|
||||
|
||||
**1b.** Vytvor BTreeMap s číslami ako kľúčmi (i32 → String). Vlož ich v náhodnom poradí. Vypíš a over, že sú zoradené.
|
||||
|
||||
**1c.** Vytvor rovnakú mapu raz ako HashMap, raz ako BTreeMap. Vypíš obe. Vidíš rozdiel v poradí?
|
||||
|
||||
---
|
||||
|
||||
## Kapitola 2: Všetko čo vieš z HashMap funguje rovnako
|
||||
|
||||
BTreeMap má **rovnaké API** ako HashMap. Všetko čo si sa naučil, funguje:
|
||||
|
||||
```rust
|
||||
let mut mapa = BTreeMap::new();
|
||||
|
||||
// insert — rovnaké
|
||||
mapa.insert("Anna".to_string(), 25);
|
||||
let stara = mapa.insert("Anna".to_string(), 26); // Some(25)
|
||||
|
||||
// get — rovnaké
|
||||
let vek = mapa.get("Anna"); // Some(&26)
|
||||
|
||||
// contains_key — rovnaké
|
||||
let je_tam = mapa.contains_key("Anna"); // true
|
||||
|
||||
// remove — rovnaké
|
||||
let odstraneny = mapa.remove("Anna"); // Some(26)
|
||||
|
||||
// len, is_empty — rovnaké
|
||||
let pocet = mapa.len();
|
||||
let prazdna = mapa.is_empty();
|
||||
|
||||
// entry API — rovnaké!
|
||||
*mapa.entry("Boris".to_string()).or_insert(0) += 1;
|
||||
mapa.entry("Cyril".to_string()).or_default();
|
||||
mapa.entry("Dana".to_string())
|
||||
.and_modify(|v| *v += 1)
|
||||
.or_insert(1);
|
||||
|
||||
// get_mut — rovnaké
|
||||
if let Some(vek) = mapa.get_mut("Boris") {
|
||||
*vek += 10;
|
||||
}
|
||||
|
||||
// iterácia — rovnaká syntax, ale ZORADENÉ
|
||||
for (k, v) in &mapa { /* zoradené podľa kľúča */ }
|
||||
for k in mapa.keys() { /* zoradené */ }
|
||||
for v in mapa.values() { /* v poradí podľa zoradených kľúčov */ }
|
||||
for v in mapa.values_mut() { *v += 1; }
|
||||
```
|
||||
|
||||
Jediný rozdiel je, že výstup je vždy zoradený.
|
||||
|
||||
### Úlohy 2
|
||||
|
||||
**2a.** Spočítaj výskyt každého znaku v `"abrakadabra"` do BTreeMap. Vypíš. V akom poradí sú znaky?
|
||||
|
||||
**2b.** Máš vektor slov. Zoskup ich podľa prvého písmena do `BTreeMap<char, Vec<String>>`. Over, že písmená sú zoradené.
|
||||
|
||||
**2c.** Napíš funkciu:
|
||||
```rust
|
||||
fn pocitaj_slova(text: &str) -> BTreeMap<String, usize>
|
||||
```
|
||||
Počet výskytov každého slova, zoradené abecedne.
|
||||
|
||||
---
|
||||
|
||||
## Kapitola 3: Range queries — to čo HashMap nevie
|
||||
|
||||
Najväčšia výhoda BTreeMap: vieš sa pýtať na **rozsahy** kľúčov.
|
||||
|
||||
### range — podmnožina podľa rozsahu kľúčov
|
||||
|
||||
```rust
|
||||
let mut mapa = BTreeMap::new();
|
||||
mapa.insert(1, "jedna");
|
||||
mapa.insert(2, "dva");
|
||||
mapa.insert(3, "tri");
|
||||
mapa.insert(4, "štyri");
|
||||
mapa.insert(5, "päť");
|
||||
mapa.insert(6, "šesť");
|
||||
mapa.insert(7, "sedem");
|
||||
|
||||
// Kľúče od 3 do 5 (vrátane oboch)
|
||||
for (k, v) in mapa.range(3..=5) {
|
||||
println!("{}: {}", k, v);
|
||||
}
|
||||
// 3: tri
|
||||
// 4: štyri
|
||||
// 5: päť
|
||||
|
||||
// Kľúče od 3 (bez 6)
|
||||
for (k, v) in mapa.range(3..6) {
|
||||
println!("{}: {}", k, v);
|
||||
}
|
||||
// 3: tri
|
||||
// 4: štyri
|
||||
// 5: päť
|
||||
|
||||
// Kľúče od začiatku po 3 (vrátane)
|
||||
for (k, v) in mapa.range(..=3) {
|
||||
println!("{}: {}", k, v);
|
||||
}
|
||||
// 1: jedna
|
||||
// 2: dva
|
||||
// 3: tri
|
||||
|
||||
// Kľúče od 5 do konca
|
||||
for (k, v) in mapa.range(5..) {
|
||||
println!("{}: {}", k, v);
|
||||
}
|
||||
// 5: päť
|
||||
// 6: šesť
|
||||
// 7: sedem
|
||||
```
|
||||
|
||||
S Stringami to funguje abecedne:
|
||||
```rust
|
||||
let mut mapa = BTreeMap::new();
|
||||
mapa.insert("Anna".to_string(), 25);
|
||||
mapa.insert("Boris".to_string(), 30);
|
||||
mapa.insert("Cyril".to_string(), 22);
|
||||
mapa.insert("Dana".to_string(), 28);
|
||||
|
||||
// Mená od "B" po "D" (nezahrnie "D" lebo ..)
|
||||
for (meno, vek) in mapa.range("B".to_string().."D".to_string()) {
|
||||
println!("{}: {}", meno, vek);
|
||||
}
|
||||
// Boris: 30
|
||||
// Cyril: 22
|
||||
```
|
||||
|
||||
### Úlohy 3
|
||||
|
||||
**3a.** Vytvor BTreeMap s kľúčmi 1 až 10 (i32 → String s názvom čísla). Vypíš len čísla 4 až 7.
|
||||
|
||||
**3b.** Máš BTreeMap študentov (meno → priemer). Vypíš len študentov, ktorých meno začína na písmená M až Z. Použi `.range()`.
|
||||
|
||||
**3c.** Máš BTreeMap teplôt za dni v mesiaci (u32 → f64, deň → teplota). Napíš funkciu:
|
||||
```rust
|
||||
fn teploty_v_tyzdni(teploty: &BTreeMap<u32, f64>, od: u32, do_: u32) -> Vec<f64>
|
||||
```
|
||||
Vráti vektor teplôt pre dané dni.
|
||||
|
||||
---
|
||||
|
||||
## Kapitola 4: first/last — prvý a posledný kľúč
|
||||
|
||||
BTreeMap vie efektívne nájsť najmenší a najväčší kľúč:
|
||||
|
||||
```rust
|
||||
let mut mapa = BTreeMap::new();
|
||||
mapa.insert(5, "päť");
|
||||
mapa.insert(1, "jedna");
|
||||
mapa.insert(9, "deväť");
|
||||
mapa.insert(3, "tri");
|
||||
|
||||
// Prvý (najmenší) pár
|
||||
let prvy = mapa.first_key_value();
|
||||
// Some((&1, &"jedna"))
|
||||
|
||||
// Posledný (najväčší) pár
|
||||
let posledny = mapa.last_key_value();
|
||||
// Some((&9, &"deväť"))
|
||||
|
||||
// Len kľúče
|
||||
let prvy_kluc = mapa.keys().next(); // Some(&1)
|
||||
let posledny_kluc = mapa.keys().last(); // Some(&9)
|
||||
```
|
||||
|
||||
Tieto operácie sú O(log n) — veľmi rýchle. HashMap toto nevie (musel by prejsť celú mapu).
|
||||
|
||||
### Úlohy 4
|
||||
|
||||
**4a.** Máš BTreeMap študentov (meno → priemer). Nájdi študenta s menom prvým v abecede a posledným v abecede.
|
||||
|
||||
**4b.** Máš BTreeMap (rok: u32 → udalosť: String). Nájdi najstaršiu a najnovšiu udalosť.
|
||||
|
||||
---
|
||||
|
||||
## Kapitola 5: Kedy HashMap, kedy BTreeMap
|
||||
|
||||
| Situácia | Použi |
|
||||
|----------|-------|
|
||||
| Nepotrebuješ poradie | HashMap (rýchlejší) |
|
||||
| Chceš zoradený výpis | BTreeMap |
|
||||
| Potrebuješ range queries | BTreeMap |
|
||||
| Potrebuješ prvý/posledný | BTreeMap |
|
||||
| Chceš maximálny výkon | HashMap |
|
||||
| Na skúške: `vypis_statistiky` zoradene | BTreeMap |
|
||||
|
||||
**Tip na skúšku:** Ak zadanie hovorí "vypíš v abecednom poradí" alebo "zoradene", použi BTreeMap. Inak HashMap stačí.
|
||||
|
||||
Konverzia medzi nimi je jednoduchá:
|
||||
```rust
|
||||
use std::collections::{HashMap, BTreeMap};
|
||||
|
||||
// HashMap → BTreeMap
|
||||
let hash: HashMap<String, i32> = /* ... */;
|
||||
let btree: BTreeMap<String, i32> = hash.into_iter().collect();
|
||||
|
||||
// BTreeMap → HashMap
|
||||
let btree: BTreeMap<String, i32> = /* ... */;
|
||||
let hash: HashMap<String, i32> = btree.into_iter().collect();
|
||||
```
|
||||
|
||||
### Úlohy 5
|
||||
|
||||
**5a.** Máš:
|
||||
```rust
|
||||
struct Zamestnanec { meno: String, oddelenie: String, plat: u32 }
|
||||
```
|
||||
Napíš funkciu `pocet_na_oddeleni(zamestnanci: &[Zamestnanec]) -> BTreeMap<String, usize>` — počet ľudí na oddelení, výstup zoradený podľa názvu oddelenia.
|
||||
|
||||
**5b.** Máš vektor slov. Spočítaj výskyt každého slova a výstup zoradeného (BTreeMap). Potom vypíš len slová, ktoré sa vyskytli viac ako 2x.
|
||||
|
||||
**5c.** Máš BTreeMap známok študenta (predmet → známka). Napíš funkcie:
|
||||
- `najlepsia_znamka(znamky: &BTreeMap<String, u8>) -> Option<(&String, &u8)>` — predmet s najlepšou (najnižšou) známkou
|
||||
- `predmety_v_rozsahu(znamky: &BTreeMap<String, u8>, od: &str, do_: &str) -> Vec<(&String, &u8)>` — predmety s názvom v danom abecednom rozsahu
|
||||
Reference in New Issue
Block a user