Skip to content

Commit 767985a

Browse files
committed
feat: add vector core structure
1 parent 0e978ab commit 767985a

2 files changed

Lines changed: 295 additions & 0 deletions

File tree

src/vector.rs

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,218 @@
22
//!
33
//! Este modulo enseñara capacidad, longitud, crecimiento amortizado, acceso por
44
//! indice y las compensaciones de memoria contigua.
5+
6+
/// Arreglo dinamico contiguo para estudiar longitud, capacidad y crecimiento.
7+
///
8+
/// Esta primera implementacion prioriza invariantes visibles y Rust seguro. Usa
9+
/// `Option<T>` como celda inicializada para evitar gestion manual de memoria; el
10+
/// capitulo explica que una implementacion industrial usa memoria sin inicializar
11+
/// y requiere `unsafe` cuidadosamente justificado.
12+
#[derive(Debug)]
13+
pub struct Vector<T> {
14+
items: Box<[Option<T>]>,
15+
len: usize,
16+
}
17+
18+
/// Error al insertar en una posicion que no existe.
19+
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
20+
pub struct InsertError {
21+
/// Indice solicitado por quien llama.
22+
pub index: usize,
23+
/// Longitud del vector en el momento de la operacion.
24+
pub len: usize,
25+
}
26+
27+
impl<T> Vector<T> {
28+
/// Crea un vector vacio sin capacidad reservada.
29+
///
30+
/// Complejidad: O(1) tiempo y O(1) espacio.
31+
#[must_use]
32+
pub fn new() -> Self {
33+
Self {
34+
items: allocate_slots(0),
35+
len: 0,
36+
}
37+
}
38+
39+
/// Crea un vector vacio con capacidad para `capacity` elementos.
40+
///
41+
/// Complejidad: O(n) tiempo y O(n) espacio, donde `n` es `capacity`, porque
42+
/// esta version segura inicializa cada celda con `None`.
43+
#[must_use]
44+
pub fn with_capacity(capacity: usize) -> Self {
45+
Self {
46+
items: allocate_slots(capacity),
47+
len: 0,
48+
}
49+
}
50+
51+
/// Devuelve el numero de elementos almacenados.
52+
///
53+
/// Complejidad: O(1).
54+
#[must_use]
55+
pub fn len(&self) -> usize {
56+
self.len
57+
}
58+
59+
/// Devuelve la cantidad de elementos que caben sin crecer.
60+
///
61+
/// Complejidad: O(1).
62+
#[must_use]
63+
pub fn capacity(&self) -> usize {
64+
self.items.len()
65+
}
66+
67+
/// Indica si el vector no contiene elementos.
68+
///
69+
/// Complejidad: O(1).
70+
#[must_use]
71+
pub fn is_empty(&self) -> bool {
72+
self.len == 0
73+
}
74+
75+
/// Agrega `value` al final del vector.
76+
///
77+
/// Complejidad: O(1) amortizado. Cuando la capacidad se agota, crecer cuesta
78+
/// O(n) porque se mueven los elementos al nuevo bloque.
79+
pub fn push(&mut self, value: T) {
80+
if self.len == self.capacity() {
81+
self.grow();
82+
}
83+
84+
self.items[self.len] = Some(value);
85+
self.len += 1;
86+
}
87+
88+
/// Remueve y devuelve el ultimo elemento, si existe.
89+
///
90+
/// Complejidad: O(1).
91+
pub fn pop(&mut self) -> Option<T> {
92+
if self.is_empty() {
93+
return None;
94+
}
95+
96+
self.len -= 1;
97+
self.items[self.len].take()
98+
}
99+
100+
/// Devuelve una referencia al elemento en `index`, si existe.
101+
///
102+
/// Complejidad: O(1).
103+
#[must_use]
104+
pub fn get(&self, index: usize) -> Option<&T> {
105+
if index >= self.len {
106+
return None;
107+
}
108+
109+
self.items[index].as_ref()
110+
}
111+
112+
/// Devuelve una referencia mutable al elemento en `index`, si existe.
113+
///
114+
/// Complejidad: O(1).
115+
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
116+
if index >= self.len {
117+
return None;
118+
}
119+
120+
self.items[index].as_mut()
121+
}
122+
123+
/// Inserta `value` en `index`, desplazando a la derecha los elementos
124+
/// posteriores.
125+
///
126+
/// `index == len` es valido y equivale a `push`. Un indice mayor que `len`
127+
/// devuelve `InsertError`.
128+
///
129+
/// Complejidad: O(n) en el peor caso por el desplazamiento.
130+
pub fn insert(&mut self, index: usize, value: T) -> Result<(), InsertError> {
131+
if index > self.len {
132+
return Err(InsertError {
133+
index,
134+
len: self.len,
135+
});
136+
}
137+
138+
if self.len == self.capacity() {
139+
self.grow();
140+
}
141+
142+
for current in (index..self.len).rev() {
143+
self.items[current + 1] = self.items[current].take();
144+
}
145+
146+
self.items[index] = Some(value);
147+
self.len += 1;
148+
149+
Ok(())
150+
}
151+
152+
/// Remueve y devuelve el elemento en `index`, si existe.
153+
///
154+
/// Complejidad: O(n) en el peor caso por el desplazamiento.
155+
pub fn remove(&mut self, index: usize) -> Option<T> {
156+
if index >= self.len {
157+
return None;
158+
}
159+
160+
let removed = self.items[index].take();
161+
162+
for current in index + 1..self.len {
163+
self.items[current - 1] = self.items[current].take();
164+
}
165+
166+
self.len -= 1;
167+
self.items[self.len] = None;
168+
169+
removed
170+
}
171+
172+
/// Remueve todos los elementos sin liberar la capacidad reservada.
173+
///
174+
/// Complejidad: O(n).
175+
pub fn clear(&mut self) {
176+
for index in 0..self.len {
177+
self.items[index] = None;
178+
}
179+
180+
self.len = 0;
181+
}
182+
183+
/// Itera sobre referencias a los elementos almacenados.
184+
///
185+
/// Complejidad: O(1) para crear el iterador y O(n) para consumirlo completo.
186+
pub fn iter(&self) -> impl Iterator<Item = &T> {
187+
self.items[..self.len]
188+
.iter()
189+
.map(|slot| slot.as_ref().expect("occupied slots before len"))
190+
}
191+
192+
fn grow(&mut self) {
193+
let next_capacity = if self.capacity() == 0 {
194+
1
195+
} else {
196+
self.capacity() * 2
197+
};
198+
199+
let mut next_items = allocate_slots(next_capacity);
200+
for index in 0..self.len {
201+
next_items[index] = self.items[index].take();
202+
}
203+
204+
self.items = next_items;
205+
}
206+
}
207+
208+
impl<T> Default for Vector<T> {
209+
fn default() -> Self {
210+
Self::new()
211+
}
212+
}
213+
214+
fn allocate_slots<T>(capacity: usize) -> Box<[Option<T>]> {
215+
std::iter::repeat_with(|| None)
216+
.take(capacity)
217+
.collect::<Vec<_>>()
218+
.into_boxed_slice()
219+
}

tests/vector_test.rs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
use rust_data_structures::vector::Vector;
2+
3+
#[test]
4+
fn push_and_pop_preserve_lifo_order_at_the_back() {
5+
let mut values = Vector::new();
6+
7+
assert!(values.is_empty());
8+
assert_eq!(values.len(), 0);
9+
assert_eq!(values.capacity(), 0);
10+
11+
values.push("a");
12+
values.push("b");
13+
14+
assert_eq!(values.len(), 2);
15+
assert!(values.capacity() >= 2);
16+
assert_eq!(values.pop(), Some("b"));
17+
assert_eq!(values.pop(), Some("a"));
18+
assert_eq!(values.pop(), None);
19+
assert!(values.is_empty());
20+
}
21+
22+
#[test]
23+
fn get_and_get_mut_access_existing_indexes_only() {
24+
let mut values = Vector::with_capacity(4);
25+
26+
values.push(10);
27+
values.push(20);
28+
29+
assert_eq!(values.capacity(), 4);
30+
assert_eq!(values.get(0), Some(&10));
31+
assert_eq!(values.get(1), Some(&20));
32+
assert_eq!(values.get(2), None);
33+
34+
*values.get_mut(1).expect("index 1 exists") = 25;
35+
36+
assert_eq!(values.get(1), Some(&25));
37+
}
38+
39+
#[test]
40+
fn insert_and_remove_shift_elements_without_losing_order() {
41+
let mut values = Vector::new();
42+
43+
values.push(1);
44+
values.push(3);
45+
values
46+
.insert(1, 2)
47+
.expect("index 1 is a valid insertion point");
48+
values.insert(3, 4).expect("len is a valid insertion point");
49+
50+
assert_eq!(values.len(), 4);
51+
assert_eq!(values.get(0), Some(&1));
52+
assert_eq!(values.get(1), Some(&2));
53+
assert_eq!(values.get(2), Some(&3));
54+
assert_eq!(values.get(3), Some(&4));
55+
assert!(values.insert(5, 99).is_err());
56+
57+
assert_eq!(values.remove(1), Some(2));
58+
assert_eq!(values.remove(2), Some(4));
59+
assert_eq!(values.remove(2), None);
60+
assert_eq!(values.get(0), Some(&1));
61+
assert_eq!(values.get(1), Some(&3));
62+
}
63+
64+
#[test]
65+
fn iter_and_clear_expose_values_without_leaking_capacity() {
66+
let mut values = Vector::with_capacity(8);
67+
68+
values.push("vector");
69+
values.push("heap");
70+
values.push("trie");
71+
72+
let collected = values.iter().copied().collect::<Vec<_>>();
73+
assert_eq!(collected, vec!["vector", "heap", "trie"]);
74+
75+
values.clear();
76+
77+
assert!(values.is_empty());
78+
assert_eq!(values.capacity(), 8);
79+
assert_eq!(values.iter().next(), None);
80+
}

0 commit comments

Comments
 (0)