Skip to content

Commit 7a69ce7

Browse files
committed
feat: add linked list core structure
1 parent f520cf2 commit 7a69ce7

2 files changed

Lines changed: 477 additions & 0 deletions

File tree

src/linked_list.rs

Lines changed: 360 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,363 @@
22
//!
33
//! Este modulo enseñara nodos, enlaces, propiedad de memoria, insercion,
44
//! eliminacion e iteracion sin esconder los costos de localidad.
5+
6+
/// Lista enlazada simple para estudiar nodos, enlaces y ownership.
7+
///
8+
/// Esta implementacion usa solo Rust seguro. Cada nodo posee su sucesor con
9+
/// `Box<Node<T>>`, y la lista posee el primer nodo mediante `head`.
10+
///
11+
/// ```
12+
/// use rust_data_structures::linked_list::LinkedList;
13+
///
14+
/// let mut list = LinkedList::new();
15+
/// list.push_back("a");
16+
/// list.push_back("b");
17+
///
18+
/// assert_eq!(list.front(), Some(&"a"));
19+
/// assert_eq!(list.back(), Some(&"b"));
20+
/// assert_eq!(list.iter().copied().collect::<Vec<_>>(), vec!["a", "b"]);
21+
/// ```
22+
#[derive(Debug)]
23+
pub struct LinkedList<T> {
24+
head: Option<Box<Node<T>>>,
25+
len: usize,
26+
}
27+
28+
#[derive(Debug)]
29+
struct Node<T> {
30+
value: T,
31+
next: Option<Box<Node<T>>>,
32+
}
33+
34+
/// Iterador inmutable sobre una [`LinkedList`].
35+
///
36+
/// ```
37+
/// use rust_data_structures::linked_list::LinkedList;
38+
///
39+
/// let mut list = LinkedList::new();
40+
/// list.push_back(1);
41+
/// list.push_back(2);
42+
///
43+
/// let collected = list.iter().copied().collect::<Vec<_>>();
44+
/// assert_eq!(collected, vec![1, 2]);
45+
/// ```
46+
#[derive(Debug, Clone)]
47+
pub struct Iter<'a, T> {
48+
next: Option<&'a Node<T>>,
49+
}
50+
51+
impl<T> LinkedList<T> {
52+
/// Crea una lista vacia.
53+
///
54+
/// Complejidad: O(1).
55+
///
56+
/// ```
57+
/// use rust_data_structures::linked_list::LinkedList;
58+
///
59+
/// let list = LinkedList::<i32>::new();
60+
/// assert!(list.is_empty());
61+
/// ```
62+
#[must_use]
63+
pub fn new() -> Self {
64+
Self { head: None, len: 0 }
65+
}
66+
67+
/// Devuelve el numero de elementos.
68+
///
69+
/// Complejidad: O(1).
70+
///
71+
/// ```
72+
/// use rust_data_structures::linked_list::LinkedList;
73+
///
74+
/// let mut list = LinkedList::new();
75+
/// list.push_front("nodo");
76+
///
77+
/// assert_eq!(list.len(), 1);
78+
/// ```
79+
#[must_use]
80+
pub fn len(&self) -> usize {
81+
self.len
82+
}
83+
84+
/// Indica si la lista no contiene elementos.
85+
///
86+
/// Complejidad: O(1).
87+
///
88+
/// ```
89+
/// use rust_data_structures::linked_list::LinkedList;
90+
///
91+
/// let mut list = LinkedList::new();
92+
/// assert!(list.is_empty());
93+
///
94+
/// list.push_back("dato");
95+
/// assert!(!list.is_empty());
96+
/// ```
97+
#[must_use]
98+
pub fn is_empty(&self) -> bool {
99+
self.len == 0
100+
}
101+
102+
/// Inserta `value` al inicio.
103+
///
104+
/// Complejidad: O(1).
105+
///
106+
/// ```
107+
/// use rust_data_structures::linked_list::LinkedList;
108+
///
109+
/// let mut list = LinkedList::new();
110+
/// list.push_front("b");
111+
/// list.push_front("a");
112+
///
113+
/// assert_eq!(list.iter().copied().collect::<Vec<_>>(), vec!["a", "b"]);
114+
/// ```
115+
pub fn push_front(&mut self, value: T) {
116+
let next = self.head.take();
117+
self.head = Some(Box::new(Node { value, next }));
118+
self.len += 1;
119+
}
120+
121+
/// Inserta `value` al final.
122+
///
123+
/// Complejidad: O(n), porque esta lista simple no guarda puntero mutable al
124+
/// ultimo nodo.
125+
///
126+
/// ```
127+
/// use rust_data_structures::linked_list::LinkedList;
128+
///
129+
/// let mut list = LinkedList::new();
130+
/// list.push_back("a");
131+
/// list.push_back("b");
132+
///
133+
/// assert_eq!(list.iter().copied().collect::<Vec<_>>(), vec!["a", "b"]);
134+
/// ```
135+
pub fn push_back(&mut self, value: T) {
136+
let new_node = Box::new(Node { value, next: None });
137+
let mut cursor = &mut self.head;
138+
139+
while let Some(node) = cursor {
140+
cursor = &mut node.next;
141+
}
142+
143+
*cursor = Some(new_node);
144+
self.len += 1;
145+
}
146+
147+
/// Remueve y devuelve el primer elemento, si existe.
148+
///
149+
/// Complejidad: O(1).
150+
///
151+
/// ```
152+
/// use rust_data_structures::linked_list::LinkedList;
153+
///
154+
/// let mut list = LinkedList::new();
155+
/// list.push_back(10);
156+
///
157+
/// assert_eq!(list.pop_front(), Some(10));
158+
/// assert_eq!(list.pop_front(), None);
159+
/// ```
160+
pub fn pop_front(&mut self) -> Option<T> {
161+
let head = self.head.take()?;
162+
self.head = head.next;
163+
self.len -= 1;
164+
Some(head.value)
165+
}
166+
167+
/// Remueve y devuelve el ultimo elemento, si existe.
168+
///
169+
/// Complejidad: O(n).
170+
///
171+
/// ```
172+
/// use rust_data_structures::linked_list::LinkedList;
173+
///
174+
/// let mut list = LinkedList::new();
175+
/// list.push_back(10);
176+
/// list.push_back(20);
177+
///
178+
/// assert_eq!(list.pop_back(), Some(20));
179+
/// assert_eq!(list.pop_back(), Some(10));
180+
/// ```
181+
pub fn pop_back(&mut self) -> Option<T> {
182+
match self.len {
183+
0 => None,
184+
1 => self.pop_front(),
185+
_ => {
186+
let mut current = self.head.as_mut().expect("len > 1 implies head");
187+
188+
while current
189+
.next
190+
.as_ref()
191+
.and_then(|next| next.next.as_ref())
192+
.is_some()
193+
{
194+
current = current.next.as_mut().expect("next exists");
195+
}
196+
197+
let tail = current.next.take().expect("tail exists");
198+
self.len -= 1;
199+
Some(tail.value)
200+
}
201+
}
202+
}
203+
204+
/// Devuelve una referencia al primer elemento.
205+
///
206+
/// Complejidad: O(1).
207+
///
208+
/// ```
209+
/// use rust_data_structures::linked_list::LinkedList;
210+
///
211+
/// let mut list = LinkedList::new();
212+
/// list.push_front("primero");
213+
///
214+
/// assert_eq!(list.front(), Some(&"primero"));
215+
/// ```
216+
#[must_use]
217+
pub fn front(&self) -> Option<&T> {
218+
self.head.as_ref().map(|node| &node.value)
219+
}
220+
221+
/// Devuelve una referencia al ultimo elemento.
222+
///
223+
/// Complejidad: O(n).
224+
///
225+
/// ```
226+
/// use rust_data_structures::linked_list::LinkedList;
227+
///
228+
/// let mut list = LinkedList::new();
229+
/// list.push_back("ultimo");
230+
///
231+
/// assert_eq!(list.back(), Some(&"ultimo"));
232+
/// ```
233+
#[must_use]
234+
pub fn back(&self) -> Option<&T> {
235+
let mut current = self.head.as_deref()?;
236+
237+
while let Some(next) = current.next.as_deref() {
238+
current = next;
239+
}
240+
241+
Some(&current.value)
242+
}
243+
244+
/// Remueve y devuelve el elemento en `index`, si existe.
245+
///
246+
/// Complejidad: O(n).
247+
///
248+
/// ```
249+
/// use rust_data_structures::linked_list::LinkedList;
250+
///
251+
/// let mut list = LinkedList::new();
252+
/// list.push_back("a");
253+
/// list.push_back("b");
254+
/// list.push_back("c");
255+
///
256+
/// assert_eq!(list.remove(1), Some("b"));
257+
/// assert_eq!(list.iter().copied().collect::<Vec<_>>(), vec!["a", "c"]);
258+
/// ```
259+
pub fn remove(&mut self, index: usize) -> Option<T> {
260+
if index >= self.len {
261+
return None;
262+
}
263+
264+
if index == 0 {
265+
return self.pop_front();
266+
}
267+
268+
let mut previous = self.head.as_mut().expect("index > 0 implies head");
269+
for _ in 0..index - 1 {
270+
previous = previous.next.as_mut().expect("index is inside len");
271+
}
272+
273+
let mut removed = previous.next.take().expect("index is inside len");
274+
previous.next = removed.next.take();
275+
self.len -= 1;
276+
277+
Some(removed.value)
278+
}
279+
280+
/// Remueve todos los nodos.
281+
///
282+
/// Complejidad: O(n).
283+
///
284+
/// ```
285+
/// use rust_data_structures::linked_list::LinkedList;
286+
///
287+
/// let mut list = LinkedList::new();
288+
/// list.push_back(1);
289+
/// list.clear();
290+
///
291+
/// assert!(list.is_empty());
292+
/// ```
293+
pub fn clear(&mut self) {
294+
while self.pop_front().is_some() {}
295+
}
296+
297+
/// Itera sobre referencias a los elementos en orden de enlaces.
298+
///
299+
/// Complejidad: O(1) para crear el iterador y O(n) para consumirlo completo.
300+
///
301+
/// ```
302+
/// use rust_data_structures::linked_list::LinkedList;
303+
///
304+
/// let mut list = LinkedList::new();
305+
/// list.push_back(2);
306+
/// list.push_back(3);
307+
///
308+
/// let sum: i32 = list.iter().copied().sum();
309+
/// assert_eq!(sum, 5);
310+
/// ```
311+
#[must_use]
312+
pub fn iter(&self) -> Iter<'_, T> {
313+
Iter {
314+
next: self.head.as_deref(),
315+
}
316+
}
317+
}
318+
319+
impl<T> Default for LinkedList<T> {
320+
fn default() -> Self {
321+
Self::new()
322+
}
323+
}
324+
325+
impl<'a, T> Iterator for Iter<'a, T> {
326+
type Item = &'a T;
327+
328+
fn next(&mut self) -> Option<Self::Item> {
329+
let node = self.next?;
330+
self.next = node.next.as_deref();
331+
Some(&node.value)
332+
}
333+
}
334+
335+
#[cfg(test)]
336+
mod tests {
337+
use super::LinkedList;
338+
339+
#[test]
340+
fn len_matches_number_of_links_after_mixed_operations() {
341+
let mut list = LinkedList::new();
342+
343+
list.push_front(2);
344+
list.push_front(1);
345+
list.push_back(3);
346+
list.remove(1);
347+
348+
assert_eq!(list.len(), 2);
349+
assert_eq!(list.iter().copied().collect::<Vec<_>>(), vec![1, 3]);
350+
}
351+
352+
#[test]
353+
fn clear_is_idempotent() {
354+
let mut list = LinkedList::new();
355+
356+
list.push_back("a");
357+
list.clear();
358+
list.clear();
359+
360+
assert!(list.is_empty());
361+
assert_eq!(list.pop_front(), None);
362+
assert_eq!(list.pop_back(), None);
363+
}
364+
}

0 commit comments

Comments
 (0)