diff --git a/src/backing/indexed/binary_heap.rs b/src/backing/indexed/binary_heap.rs index 2f5dbc6..48fa252 100644 --- a/src/backing/indexed/binary_heap.rs +++ b/src/backing/indexed/binary_heap.rs @@ -13,6 +13,14 @@ pub struct IndexedBinaryHeap< indices: HashMap, } +impl Default + for IndexedBinaryHeap +{ + fn default() -> Self { + Self::new() + } +} + impl IndexedBinaryHeap { @@ -54,49 +62,47 @@ impl if i > self.data.len() { // Tried to sift a non-existent index Err(SiftError::new(i, self.data.len())) - } else { - if let Some(first_child) = self.data.get(i * 2 + 1).cloned() { - let smaller_child_index; - let smaller_child; + } else if let Some(first_child) = self.data.get(i * 2 + 1).cloned() { + let smaller_child_index; + let smaller_child; - // Find the smallest child and its index - if let Some(second_child) = self.data.get(i * 2 + 2).cloned() { - // Both children, use the smaller one - if first_child < second_child { - smaller_child = first_child; - smaller_child_index = i * 2 + 1; - } else { - smaller_child = second_child; - smaller_child_index = i * 2 + 2; - } - } else { - // Only one child, no choice + // Find the smallest child and its index + if let Some(second_child) = self.data.get(i * 2 + 2).cloned() { + // Both children, use the smaller one + if first_child < second_child { smaller_child = first_child; smaller_child_index = i * 2 + 1; - } - - if smaller_child < self.data[i] { - // Swap parent with child - self.data[smaller_child_index] = self.data[i].clone(); - self.indices - .insert( - self.data[smaller_child_index].clone().data(), - smaller_child_index, - ) - .unwrap(); - self.data[i] = smaller_child.clone(); - self.indices.insert(smaller_child.data(), i).unwrap(); - - // Repeat process with child - self.sift_down(smaller_child_index) } else { - // Heap property satisfied, we're done - Ok(()) + smaller_child = second_child; + smaller_child_index = i * 2 + 2; } } else { - // Base case, no children so nothing to do + // Only one child, no choice + smaller_child = first_child; + smaller_child_index = i * 2 + 1; + } + + if smaller_child < self.data[i] { + // Swap parent with child + self.data[smaller_child_index] = self.data[i].clone(); + self.indices + .insert( + self.data[smaller_child_index].clone().data(), + smaller_child_index, + ) + .unwrap(); + self.data[i] = smaller_child.clone(); + self.indices.insert(smaller_child.data(), i).unwrap(); + + // Repeat process with child + self.sift_down(smaller_child_index) + } else { + // Heap property satisfied, we're done Ok(()) } + } else { + // Base case, no children so nothing to do + Ok(()) } } @@ -147,6 +153,10 @@ impl In self.data.len() } + fn is_empty(&self) -> bool { + self.data.is_empty() + } + fn contains(&self, data: &D) -> bool { self.indices.contains_key(data) } @@ -164,7 +174,7 @@ impl In } } else { let final_index = self.data.len(); - if let Some(_) = self.indices.insert(data.clone(), final_index) { + if self.indices.insert(data.clone(), final_index).is_some() { panic!("Item was not consistently hashed") } self.data.push(Pair::new(data, priority)); @@ -174,21 +184,14 @@ impl In fn remove(&mut self, data: D) -> Option

{ if let Some(index) = self.indices.get(&data) { - if let Some(pair) = self.delete_pair(*index) { - Some(pair.get_priority().clone()) - } else { - None - } + self.delete_pair(*index) + .map(|pair| pair.get_priority().clone()) } else { None } } fn pop(&mut self) -> Option { - if let Some(pair) = self.delete_pair(0) { - Some(pair.data()) - } else { - None - } + self.delete_pair(0).map(|pair| pair.data()) } } diff --git a/src/backing/indexed/mod.rs b/src/backing/indexed/mod.rs index 3ebfc91..63795a6 100644 --- a/src/backing/indexed/mod.rs +++ b/src/backing/indexed/mod.rs @@ -9,6 +9,8 @@ pub trait IndexedBacking usize; + /// Whether the queue is empty + fn is_empty(&self) -> bool; /// Check if an item is already in the queue fn contains(&self, data: &D) -> bool; /// Set an item's priority, will update if the item is already enqueued diff --git a/src/backing/pure/binary_heap.rs b/src/backing/pure/binary_heap.rs index 2b43ec0..cdfcdee 100644 --- a/src/backing/pure/binary_heap.rs +++ b/src/backing/pure/binary_heap.rs @@ -8,6 +8,12 @@ pub struct BinaryHeap { data: Vec, } +impl Default for BinaryHeap { + fn default() -> Self { + Self::new() + } +} + impl BinaryHeap { /// Instantiates a new (empty) binary heap pub fn new() -> Self { @@ -43,42 +49,40 @@ impl BinaryHeap { if i > self.data.len() { // Tried to sift a non-existent index Err(SiftError::new(i, self.data.len())) - } else { - if let Some(first_child) = self.data.get(i * 2 + 1).cloned() { - let smaller_child_index; - let smaller_child; + } else if let Some(first_child) = self.data.get(i * 2 + 1).cloned() { + let smaller_child_index; + let smaller_child; - // Find the smallest child and its index - if let Some(second_child) = self.data.get(i * 2 + 2).cloned() { - // Both children, use the smaller one - if first_child < second_child { - smaller_child = first_child; - smaller_child_index = i * 2 + 1; - } else { - smaller_child = second_child; - smaller_child_index = i * 2 + 2; - } - } else { - // Only one child, no choice + // Find the smallest child and its index + if let Some(second_child) = self.data.get(i * 2 + 2).cloned() { + // Both children, use the smaller one + if first_child < second_child { smaller_child = first_child; smaller_child_index = i * 2 + 1; - } - - if smaller_child < self.data[i] { - // Swap parent with child - self.data[smaller_child_index] = self.data[i].clone(); - self.data[i] = smaller_child; - - // Repeat process with child - self.sift_down(smaller_child_index) } else { - // Heap property satisfied, we're done - Ok(()) + smaller_child = second_child; + smaller_child_index = i * 2 + 2; } } else { - // Base case, no children so nothing to do + // Only one child, no choice + smaller_child = first_child; + smaller_child_index = i * 2 + 1; + } + + if smaller_child < self.data[i] { + // Swap parent with child + self.data[smaller_child_index] = self.data[i].clone(); + self.data[i] = smaller_child; + + // Repeat process with child + self.sift_down(smaller_child_index) + } else { + // Heap property satisfied, we're done Ok(()) } + } else { + // Base case, no children so nothing to do + Ok(()) } } } @@ -127,4 +131,8 @@ impl PureBacking for BinaryHeap { fn len(&self) -> usize { self.data.len() } + + fn is_empty(&self) -> bool { + self.data.is_empty() + } } diff --git a/src/backing/pure/mod.rs b/src/backing/pure/mod.rs index 1ff9d9a..29eddc2 100644 --- a/src/backing/pure/mod.rs +++ b/src/backing/pure/mod.rs @@ -10,4 +10,6 @@ pub trait PureBacking: Send + Sync { fn pop(&mut self) -> Option; /// The number of items in the queue fn len(&self) -> usize; + /// Whether the queue is empty + fn is_empty(&self) -> bool; } diff --git a/src/queue/indexed.rs b/src/queue/indexed.rs index c83da6f..0fd76c9 100644 --- a/src/queue/indexed.rs +++ b/src/queue/indexed.rs @@ -23,10 +23,8 @@ impl IndexedQueue { #[pyo3(signature = (items=None))] fn new(items: Option>) -> PyResult { if let Some(py_object) = items { - Python::with_gil(|py| Self::from_any(py_object.bind(py))).and_then(|vec| { - Ok(Self { - backing: Box::new(IndexedBinaryHeap::from_iter(vec)), - }) + Python::with_gil(|py| Self::from_any(py_object.bind(py))).map(|vec| Self { + backing: Box::new(IndexedBinaryHeap::from_iter(vec)), }) } else { Ok(Self { @@ -88,20 +86,18 @@ impl<'py> IndexedQueue { fn from_any(object: &Bound<'py, PyAny>) -> PyResult> { if let Ok(vec) = object.extract::, f64)>>() { Ok(Self::from_vec(vec)) - } else { - if object.is_instance_of::() { - if let Ok(dict) = object.downcast::() { - Self::from_dict(dict) - } else { - Err(PyErr::new::( - "Argument claimed to be a dict but wasn't", - )) - } + } else if object.is_instance_of::() { + if let Ok(dict) = object.downcast::() { + Self::from_dict(dict) } else { Err(PyErr::new::( - "Argument was not a properly-formed dict, list, or tuple", + "Argument claimed to be a dict but wasn't", )) } + } else { + Err(PyErr::new::( + "Argument was not a properly-formed dict, list, or tuple", + )) } } diff --git a/src/queue/paired.rs b/src/queue/paired.rs index 5bb5f06..fe69514 100644 --- a/src/queue/paired.rs +++ b/src/queue/paired.rs @@ -26,10 +26,8 @@ impl PairedQueue { #[pyo3(signature = (items=None))] fn new(items: Option>) -> PyResult { if let Some(py_object) = items { - Python::with_gil(|py| Self::from_any(py_object.bind(py))).and_then(|vec| { - Ok(Self { - backing: Box::new(BinaryHeap::from_iter(vec)), - }) + Python::with_gil(|py| Self::from_any(py_object.bind(py))).map(|vec| Self { + backing: Box::new(BinaryHeap::from_iter(vec)), }) } else { Ok(Self { @@ -72,20 +70,18 @@ impl<'py> PairedQueue { fn from_any(object: &Bound<'py, PyAny>) -> PyResult, f64>>> { if let Ok(vec) = object.extract::, f64)>>() { Ok(Self::from_vec(vec)) - } else { - if object.is_instance_of::() { - if let Ok(dict) = object.downcast::() { - Self::from_dict(dict) - } else { - Err(PyErr::new::( - "Argument claimed to be a dict but wasn't", - )) - } + } else if object.is_instance_of::() { + if let Ok(dict) = object.downcast::() { + Self::from_dict(dict) } else { Err(PyErr::new::( - "Argument was not a properly-formed dict, list, or tuple", + "Argument claimed to be a dict but wasn't", )) } + } else { + Err(PyErr::new::( + "Argument was not a properly-formed dict, list, or tuple", + )) } }