# 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>`. Over, že písmená sú zoradené. **2c.** Napíš funkciu: ```rust fn pocitaj_slova(text: &str) -> BTreeMap ``` 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, od: u32, do_: u32) -> Vec ``` 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 = /* ... */; let btree: BTreeMap = hash.into_iter().collect(); // BTreeMap → HashMap let btree: BTreeMap = /* ... */; let hash: HashMap = 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` — 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) -> Option<(&String, &u8)>` — predmet s najlepšou (najnižšou) známkou - `predmety_v_rozsahu(znamky: &BTreeMap, od: &str, do_: &str) -> Vec<(&String, &u8)>` — predmety s názvom v danom abecednom rozsahu