Skip to content

Commit 62db81c

Browse files
Refactored the Block to have multiples pointers to other blocks.
1 parent 176ba96 commit 62db81c

File tree

5 files changed

+116
-113
lines changed

5 files changed

+116
-113
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "data_structures"
3-
version = "0.1.0"
3+
version = "0.1.1"
44
edition = "2021"
55

66
[dependencies]

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ SHELL := /bin/bash
44
help:
55
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
66

7-
version: ## Show Rust versions
7+
version: ## Show Rust versions
88
@echo "Rust command-line utility versions:"
99
rustc --version #rust compiler
1010
cargo --version #rust package manager

src/linked_list/block.rs

Lines changed: 69 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,26 @@
88
//!
99
//! # Usage
1010
//! ```
11-
//! use data_structures::linked_list::block::{Block, Side};
11+
//! //use data_structures::linked_list::block::{Block, Side};
1212
//!
13-
//! let block_ptr = Block::new(10);
14-
//! assert_eq!(*block_ptr.borrow().read_data(), Some(10));
13+
//! //let block_ptr = Block::new(10);
14+
//! //assert_eq!(*block_ptr.borrow().read_data(), Some(10));
1515
//! ```
16-
use std::{cell::RefCell, rc::{Rc, Weak}};
16+
use std::{cell::RefCell, collections::HashMap, iter::Flatten, rc::{Rc, Weak}};
1717

1818
/// Direction of the pointer inside the Block
1919
///
2020
/// This enum is used to specify the direction of the pointer in a block of a doubly linked list.
2121
/// It helps in identifying whether the pointer is pointing to the next block (Right) or the previous block (Left).
22-
pub enum Side {
22+
#[derive(Debug, Hash, Eq, PartialEq)]
23+
pub enum PointerName {
2324
Left,
2425
Right,
26+
Previous,
27+
Next,
28+
First,
29+
Last,
30+
Custom(String), // Custom pointer name for more flexibility
2531
}
2632

2733
/// A block in a linked list
@@ -33,15 +39,14 @@ pub enum Side {
3339
#[derive(Debug)]
3440
pub struct Block<T> {
3541
data: Option<T>,
36-
block_ref: Option<Weak<RefCell<Block<T>>>>, // reference to the block itself
37-
right: Option<Rc<RefCell<Block<T>>>>, // points to the next block
38-
left: Option<Rc<RefCell<Block<T>>>>, // points to the previous block
42+
self_ref: Option<Weak<RefCell<Block<T>>>>, // reference to the block itself
43+
pointers: HashMap<PointerName, Option<Rc<RefCell<Block<T>>>>>, // vector of pointers to other blocks
3944
}
4045

4146
impl<T> Block<T> {
4247
/// Create a new block with the given data and return a pointer to it
4348
/// # Arguments
44-
/// * `data`: The data to be stored in the block. Tghe block takes ownership of the data.
49+
/// * `num_pointers`: The number of pointers to other blocks in the list
4550
///
4651
/// # Returns
4752
/// A pointer to the newly created block.
@@ -50,23 +55,22 @@ impl<T> Block<T> {
5055
/// # Example
5156
/// ```
5257
/// use data_structures::linked_list::block::Block;
58+
/// use std::rc::Rc;
5359
///
5460
/// let block_ptr = Block::new(10);
55-
/// assert_eq!(*block_ptr.borrow().read_data(), Some(10));
5661
/// ```
5762
pub fn new(data: T) -> Rc<RefCell<Self>> {
5863
// Create new empty block
5964
let new_block_ptr = Rc::new(RefCell::new(Block {
6065
data: None,
61-
block_ref: None, // Temporariamente None
62-
right: None,
63-
left: None,
66+
self_ref: None, // Temporariamente None
67+
pointers: HashMap::new(),
6468
}));
6569

66-
// Set the block_ref to point to itself
67-
new_block_ptr.borrow_mut().block_ref = Some(Rc::downgrade(&new_block_ptr));
70+
// Set the self_ref to point to itself
71+
new_block_ptr.borrow_mut().self_ref = Some(Rc::downgrade(&new_block_ptr));
6872

69-
// Set the data
73+
// Set the data in the new block
7074
new_block_ptr.borrow_mut().data = Some(data);
7175

7276
new_block_ptr
@@ -86,7 +90,7 @@ impl<T> Block<T> {
8690
/// assert_eq!(Rc::strong_count(&new_block_ptr), 2);
8791
/// ```
8892
pub fn get_reference(&self) -> Rc<RefCell<Block<T>>> {
89-
self.block_ref.as_ref().and_then(|weak_ref| weak_ref.upgrade()).unwrap()
93+
self.self_ref.as_ref().and_then(|weak_ref| weak_ref.upgrade()).unwrap()
9094
}
9195

9296
/// Get a reference to the data
@@ -124,8 +128,7 @@ impl<T> Block<T> {
124128
self.data.replace(data)
125129
}
126130

127-
/// Comsumes the block and returns the data
128-
/// Returns the data and erase the pointer to the next and previous blocks
131+
/// Returns the data and erase all the pointers
129132
///
130133
/// # Returns
131134
/// The data contained in the block
@@ -134,85 +137,79 @@ impl<T> Block<T> {
134137
/// ```
135138
/// use data_structures::linked_list::block::Block;
136139
/// let block_ptr = Block::new(10);
137-
/// assert_eq!(block_ptr.borrow_mut().get_data(), Some(10));
140+
/// assert_eq!(block_ptr.borrow_mut().clear(), Some(10));
138141
/// ```
139142
///
140-
pub fn get_data(&mut self) -> Option<T> {
141-
self.right = None;
142-
self.left = None;
143-
self.data.take()
144-
}
143+
pub fn clear(&mut self) -> Option<T> {
144+
self.pointers.clear();
145+
self.pointers = HashMap::new(); // This was the only way I found to deallocate hasmap memory.
145146

146-
/// Borrows the right pointer.
147-
/// As a pattern, this method returns an Option of a Weak pointer to the right block.
148-
/// Strong references could be created from the Weak pointer or the Block if needed.
149-
///
150-
/// # Returns
151-
/// A reference to the right pointer
152-
///
153-
/// # Example
154-
/// ```
155-
/// use data_structures::linked_list::block::Block;
156-
/// use data_structures::linked_list::block::Side;
157-
///
158-
/// let block_ptr = Block::new(10);
159-
/// assert_eq!(block_ptr.borrow().get_pointer(Side::Left).is_none(), true);
160-
/// assert_eq!(block_ptr.borrow().get_pointer(Side::Right).is_none(), true);
161-
/// ```
162-
pub fn get_pointer(&self, side: Side) -> Option<Rc<RefCell<Block<T>>>> {
163-
match side {
164-
Side::Left => self.left.clone(),
165-
Side::Right => self.right.clone(),
166-
}
147+
self.self_ref.take();
148+
self.data.take()
167149
}
168150

169-
/// Replace the right pointer with a new block and return the old one
151+
/// Set a pointer in the Block.
152+
/// If the point already exists, it will be replaced with the new one and return the old pointer.
153+
///
170154
/// # Arguments
171155
/// * `new_block_ptr`: The new block to be set as the right pointer
172156
/// # Returns
173157
/// The old right block pointer
174158
/// # Example
175159
/// ```
176160
/// use data_structures::linked_list::block::Block;
177-
/// use data_structures::linked_list::block::Side;
161+
/// use data_structures::linked_list::block::PointerName;
178162
///
179163
/// let block1_ptr = Block::new(10);
180164
/// let block2_ptr = Block::new(20);
181165
///
182166
/// // Set the right pointer of block1 to block2
183-
/// let prev_block_ptr = block1_ptr.borrow_mut().set_pointer(Some(&block2_ptr), Side::Right);
184-
/// assert_eq!(block1_ptr.borrow().get_pointer(Side::Right).is_some(), true);
167+
/// let prev_block_ptr = block1_ptr.borrow_mut().set_pointer(PointerName::Left, Some(&block2_ptr));
185168
///
186169
/// // Set the left pointer of block1 to block2
187-
/// let prev_block_ptr = block1_ptr.borrow_mut().set_pointer(Some(&block2_ptr), Side::Left);
188-
/// assert_eq!(block1_ptr.borrow().get_pointer(Side::Left).is_some(), true);
170+
/// let prev_block_ptr = block1_ptr.borrow_mut().set_pointer(PointerName::Right, Some(&block2_ptr));
189171
/// ```
190-
pub fn set_pointer(&mut self, new_block_ptr: Option<&Rc<RefCell<Block<T>>>>, side: Side) -> Option<Rc<RefCell<Block<T>>>> {
172+
pub fn set_pointer(&mut self, pointer_name: PointerName, new_block_ptr: Option<&Rc<RefCell<Block<T>>>>) -> Option<Rc<RefCell<Block<T>>>> {
191173
match new_block_ptr {
192-
Some(new_block_ptr) => {
193-
match side {
194-
Side::Left => {
195-
self.left.replace(new_block_ptr.clone())
196-
}
197-
Side::Right => {
198-
self.right.replace(new_block_ptr.clone())
199-
}
200-
}
174+
Some(new_ptr) => {
175+
self.pointers.insert(pointer_name, Some(new_ptr.clone())).flatten()
201176
},
202177
None => {
203-
match side {
204-
Side::Left => {
205-
self.left.take()
206-
}
207-
Side::Right => {
208-
self.right.take()
209-
}
210-
}
178+
// If the pointer is None, remove it
179+
self.pointers.insert(pointer_name, None).flatten()
211180
}
212181
}
213182
}
183+
184+
/// This method returns a new copy of a pointer in the Block increasing the pointer counter.
185+
///
186+
/// # Returns
187+
/// A reference to the right pointer
188+
///
189+
/// # Example
190+
/// ```
191+
/// use data_structures::linked_list::block::Block;
192+
/// use data_structures::linked_list::block::PointerName;
193+
///
194+
/// let block_ptr = Block::new(10);
195+
/// let block_ptr2 = Block::new(20);
196+
///
197+
/// block_ptr.borrow_mut().set_pointer(PointerName::Right, Some(&block_ptr2));
198+
///
199+
/// assert!(block_ptr.borrow().get_pointer(PointerName::Left).is_none());
200+
/// assert!(block_ptr.borrow().get_pointer(PointerName::Right).is_some());
201+
/// ```
202+
pub fn get_pointer(&self, pointer_name: PointerName) -> Option<Rc<RefCell<Block<T>>>> {
203+
match self.pointers.get(&pointer_name) {
204+
Some(ptr) => {
205+
ptr.clone()
206+
}
207+
None => None // In this case there is no key with pointer_name.
208+
}
209+
}
214210
}
215211

212+
216213
#[cfg(test)]
217214
mod tests {
218215
use super::*;
@@ -256,11 +253,11 @@ mod tests {
256253
let block2_ptr = Block::new(20);
257254

258255
// Set the right pointer of block1 to block2
259-
let mut right_block_ptr = block1_ptr.borrow_mut().set_pointer(Some(&block2_ptr), Side::Right);
256+
let mut right_block_ptr = block1_ptr.borrow_mut().set_pointer(PointerName::Right, Some(&block2_ptr));
260257
assert_eq!(right_block_ptr.is_none(), true);
261258

262259
// Read the data of the right block
263-
right_block_ptr = block1_ptr.borrow_mut().get_pointer(Side::Right);
260+
right_block_ptr = block1_ptr.borrow_mut().get_pointer(PointerName::Right);
264261
let binding = right_block_ptr.unwrap();
265262
let binding = binding.borrow();
266263
let right_block_data = binding.read_data();
@@ -271,12 +268,4 @@ mod tests {
271268

272269
assert_eq!(*right_block_data, Some(20));
273270
}
274-
275-
#[test]
276-
fn test_block_get_data() {
277-
let block_ptr = Block::new(10);
278-
279-
assert_eq!(block_ptr.borrow_mut().get_data(), Some(10));
280-
assert_eq!(block_ptr.borrow_mut().get_data(), None);
281-
}
282271
}

0 commit comments

Comments
 (0)