Las colecciones en Rust permiten gestionar grupos de datos con comportamientos específicos que optimizan el rendimiento según la necesidad. Mientras que Vec es la estructura de datos genérica por excelencia, otras colecciones ofrecen propiedades de ordenación, unicidad o eficiencia en los extremos.
BTreeMap y BTreeSet implementan una estructura de árbol B. A diferencia de HashMap, que utiliza funciones hash para un acceso en tiempo constante $O(1)$ pero no mantiene orden, BTreeMap mantiene sus claves ordenadas. Esto es esencial cuando se requiere iterar sobre los elementos en un orden específico o cuando se necesitan consultas por rangos mediante el método .range(). Su complejidad de acceso es $O(\log n)$.
Para conjuntos de elementos únicos, existen HashSet y BTreeSet. HashSet es la opción estándar para comprobaciones de pertenencia rápidas debido a su rendimiento basado en hash. BTreeSet es su contraparte ordenada; se utiliza cuando los elementos únicos deben estar siempre organizados. Ambas permiten realizar operaciones matemáticas de conjuntos como intersección, unión y diferencia.
Para flujos de datos que requieren inserciones y extracciones eficientes tanto al principio como al final, se utiliza VecDeque. A diferencia de un Vec convencional, donde insert(0, x) es una operación costosa de $O(n)$ debido al desplazamiento de elementos, VecDeque utiliza un ring buffer (buffer circular) que permite operaciones push_front y pop_front en tiempo constante amortizado $O(1)$.
Finalmente, BinaryHeap es una implementación de un max-heap (montículo máximo). Es una estructura ideal para colas de prioridad, donde siempre se necesita acceder al elemento con el mayor valor. El método .pop() siempre extraerá el elemento más grande de la colección, manteniendo la estructura para que el siguiente elemento más grande sea el próximo en la cima.
use std::collections::{BTreeMap, HashSet, VecDeque, BinaryHeap};
fn main() {
// --- BTreeMap: Mantiene las claves ordenadas y permite rangos ---
let mut map_scores = BTreeMap::new();
map_scores.insert(10, "Junior");
map_scores.insert(50, "Senior");
map_scores.insert(30, "Mid");
println!("--- BTreeMap (Rango 10 a 40) ---");
// El método range permite obtener una vista de un subconjunto de claves
for (&id, &rank) in map_scores.range(10..=40) {
println!("ID: {}, Rank: {}", id, rank);
}
// --- HashSet: Elementos únicos y operaciones de conjuntos ---
let set_a: HashSet<_> = [1, 2, 3].iter().cloned().collect();
let set_b: HashSet<_> = [2, 3, 4].iter().cloned().collect();
println!("\n--- HashSet (Intersección) ---");
let intersection = set_a.intersection(&set_b);
println!("Intersección (elementos comunes): {:?}", intersection.collect::<Vec<_>>());
// --- VecDeque: Cola de doble extremo (Double-ended queue) ---
let mut deque_ops = VecDeque::new();
deque_ops.push_back(1); // [1]
deque_ops.push_front(0); // [0, 1] - Operación O(1)
deque_ops.push_back(2); // [0, 1, 2]
println!("\n--- VecDeque ---");
println!("Deque completo: {:?}", deque_ops);
deque_ops.pop_front(); // Elimina el 0
println!("Tras pop_front: {:?}", deque_ops);
// --- BinaryHeap: Max-Heap para colas de prioridad ---
let mut priority_queue = BinaryHeap::new();
priority_queue.push(5);
priority_queue.push(100);
priority_queue.push(50);
println!("\n--- BinaryHeap (Max-Heap) ---");
// peek() permite ver el elemento mayor sin removerlo
println!("Máximo actual (peek): {:?}", priority_queue.peek());
// pop() extrae el elemento mayor de la estructura
println!("Mayor elemento extraído (pop): {:?}", priority_queue.pop());
println!("Siguiente mayor (pop): {:?}", priority_queue.pop());
}
Explicación del Código
map_scores: Es una instancia deBTreeMap<i32, &str>. Al insertar valores con claves10,50y30, la estructura los reorganiza internamente para mantener el orden. El métodorange(10..=40)utiliza un rango inclusivo para iterar sobre las claves que cumplen la condición, imprimiendo primero el ID10y luego el30.set_ayset_b: Son instancias deHashSet<i32>. El métodointersection(&set_b)busca qué elementos están presentes en ambos conjuntos (en este caso,2y3). El resultado se recolecta en unVecpara su impresión.deque_ops: Es unVecDeque<i32>. Se utilizapush_front(0)para demostrar que añadir elementos al inicio es eficiente ($O(1)$) gracias a su arquitectura de buffer circular. Posteriormente,pop_front()elimina el primer elemento de la cola.priority_queue: Es unBinaryHeap<i32>. Debido a su naturaleza de max-heap, al insertar5,100y50, el elemento100queda en la raíz.peek()devuelve una referencia al100, y los llamados sucesivos apop()extraen los valores en orden descendente:100, luego50.
N° 74