Files
JR-priprava-na-skusku/priprava/rust_priprava5.md
2026-02-26 18:59:33 +01:00

7.5 KiB

BTreeMap — krok za krokom

Každá kapitola: prečítaj, pozri príklady, urob úlohy. Až potom choď ďalej.

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
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:

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:

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:

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

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:

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:

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ľúč:

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á:

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áš:

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