Delete a node in singly linked list in Rust - data-structures

I am new to Rust and want to write linked list in Rust to have fun. I am confused about how to delete a node in the linked list. Here is my simple code.
#[derive(Debug)]
struct Node{
v: usize,
next: Option<Box<Node>>,
}
struct LinkedList {
head: Option<Box<Node>>,
}
impl LinkedList {
fn remove(&mut self, v: usize) -> Option<usize> {
let mut current_node: &mut Option<Box<Node>> = &mut self.head;
loop {
match current_node {
None => break,
Some(node) => {
if node.v == v {
// current_node = what?
// ???????????????
break;
} else {
current_node = &mut node.next;
}
},
};
}
match current_node.take().map(|x| *x) {
Some(node) => {
*current_node = node.next;
return Some(node.v)
},
None => None,
}
}
}
And here is the rust playground. I am using the nightly version and edition = 2018. In the loop, I try to find the node whose next node contains the value that I search for. However, I am confused about what to write in the ?? position.

There isn't really code that can go in that space to fix it; you'll need to make some bigger changes.
One of the problems is that you have mutably borrowed the current node in current_node, but then need to mutate it while that reference still exists.
Making use of non-lexical lifetimes in Edition 2018, you can do:
impl LinkedList {
fn remove(&mut self, v: usize) -> Option<usize> {
let mut current = &mut self.head;
loop {
match current {
None => return None,
Some(node) if node.v == v => {
*current = node.next.take();
return Some(v);
},
Some(node) => {
current = &mut node.next;
}
}
}
}
}
Somehow, using the match guard if node.v == v to make two match arms, instead of using an if condition inside one match arm, lets the borrower checker deduce that this is safe. I'm not sure why the if statement inside the match arm isn't allowed - there are some of the opinion that this could be a bug.

inspire by above answer, my solution is:
fn removeKFromList(mut head: ListNode<i32>, k: i32) -> ListNode<i32> {
if head.is_none() {
return None;
}
let mut current = &mut head;
loop {
match current {
None => break,
Some(node) if node.value == k => {
*current = node.next.take();
},
Some(node) => {
current = &mut node.next;
}
}
}
return head;
}

Here is solution, if you have generic List, which accepts arbitrary type of content type T and returns deleted content to caller:
impl<T> LinkedList<T> {
pub fn remove_f<F: Fn(&T) -> bool>(&mut self, comparator: F) -> Option<T> {
let mut curr_link = &mut self.head;
loop {
match curr_link {
None => return None,
Some(node_ref) if comparator(&node_ref.elem) => {
let node = curr_link.take().unwrap();
*curr_link = node.next;
return Some(node.elem);
},
Some(node) => curr_link = &mut node.next,
};
}
}
}
Use example, assume T = &str and list contains element with value "1" and no element with value "smth":
assert_eq!(list.remove_f(|node| "1".eq(node.deref())), Some("1"));
assert_eq!(list.remove_f(|node| "smth".eq(node.deref())), None);

Related

Iterative filter function that modifies tree like structure

I have a structure like
struct Node {
pub id: String,
pub dis: String,
pub parent: Option<NodeRefNodeRefWeak>,
pub children: Vec<NodeRef>,
}
pub type NodeRef = Rc<RefCell<Node>>;
pub type NodeRefNodeRefWeak = Weak<RefCell<Node>>;
I also have a start of a function that can iterate this structure to
pull out a match on a node id but it has issues.
What I would like is for this function to return the parent node of the whole tree with ONLY the branches that have a match somewhere on the branch.
Children past the search node can be removed.
Ie a function that filters all other nodes out of the tree.
For example with my rust playground link I would like it to return
level0_node_#1 (level0_node_#1)
level1_node_4 (level1_node_4)
level2_node_4_3 (level2_node_4_3)
level3_node_4_3_2 (level3_node_4_3_2)
However, using the recursive approach as below causes real issue with already borrowed errors when trying to remove branches etc.
Is there a way to achieve this filter function?
I have a test in the Rust playground.
fn tree_filter_node_objects<F>(node: &NodeRef, f: F) -> Vec<NodeRef>
where F: Fn(&str) -> bool + Copy {
let mut filtered_nodes: Vec<NodeRef> = vec![];
let mut borrow = node.borrow_mut();
if f(&borrow.id) {
filtered_nodes.push(node.clone());
}
for n in borrow.children.iter() {
let children_filtered = tree_filter_node_objects(n, f);
for c in children_filtered.iter() {
filtered_nodes.push(c.clone());
}
}
filtered_nodes
}
In the end I used this iterative approach.
pub fn tree_filter_node_dfs<F>(root: &NodeRef, f: F) -> Vec<NodeRef>
where F: Fn(&BmosHaystackObject) -> bool + Copy {
let mut filtered_nodes: Vec<NodeRef> = vec![];
let mut cur_node: Option<NodeRef> = Some(root.clone());
let mut last_visited_child: Option<NodeRef> = None;
let mut next_child: Option<NodeRef>;
let mut run_visit: bool = true;
while cur_node.is_some() {
if run_visit {
let n = cur_node.as_ref().unwrap();
if f(&n.borrow().object) {
}
}
if last_visited_child.is_none() {
let children = cur_node.as_ref().unwrap().borrow().children.clone();
if children.len() > 0 {
next_child = Some(children[0].clone());
}
else {
next_child = None;
}
}
else {
next_child = tree_filter_node_get_next_sibling(last_visited_child.as_ref().unwrap());
}
if next_child.is_some() {
last_visited_child = None;
cur_node = next_child;
run_visit = true;
}
else {
last_visited_child = cur_node;
cur_node = tree_node_parent_node(&last_visited_child.clone().unwrap().clone());
run_visit = false;
}
}
filtered_nodes
}

Trie: cannot borrow `_` as mutable more than once at a time

I want to implement some basic methods for Trie.
use std::collections::HashMap;
#[derive(Debug)]
struct TrieNode {
chs: HashMap<char, TrieNode>,
value: Option<i32>,
}
#[derive(Debug)]
struct Trie {
root: TrieNode,
}
impl Trie {
fn new() -> Trie {
Trie {
root: TrieNode {
chs: HashMap::new(),
value: None,
},
}
}
fn add_string(&mut self, string: String, value: i32) {
let mut current_node = &mut self.root;
for c in string.chars() {
current_node = current_node.chs.entry(c).or_insert(TrieNode {
chs: HashMap::new(),
value: None,
});
}
current_node.value = Some(value);
}
fn delete(&mut self, key: &String) -> Option<i32> {
if key.is_empty() {
// if key is empty, no need to delete
return None;
}
let mut current_node = &mut self.root;
for (ind, ch) in key.chars().enumerate() {
match current_node.chs.get_mut(&ch) {
Some(node) => {
if ind < key.len() - 1 {
current_node = node;
}
}
None => return None,
}
}
// here current_node is actually the previous node of the deleted node
let temp = current_node.chs.remove(&key.chars().last().unwrap());
match temp {
Some(node) => node.value,
None => None,
}
}
}
The method delete is to remove a key (from a Trie) and returns the value corresponding to that key. However, I got the following error.
error[E0499]: cannot borrow `current_node.chs` as mutable more than once at a time
--> src/main.rs:118:19
|
118 | match current_node.chs.get_mut(&ch) {
| ^^^^^^^^^^^^^^^^ mutable borrow starts here in previous iteration of loop
I'm not exactly sure where the borrow checker is getting tripped up, but you can fix it by hoisting the if check:
let mut current_node = &mut self.root;
for (ind, ch) in key.chars().enumerate() {
if ind < key.len() - 1 {
match current_node.chs.get_mut(&ch) {
Some(node) => {
current_node = node;
}
None => return None,
}
}
}
It skips over even checking if the leaf node exists, but your remove( match already covers that case.
Also, your ind < key.len() - 1 check assumes that the last character is ascii. It may be true for your use case, but if not you can use this answer to iterate until the penultimate character instead.
As the error message explains, you cannot borrow a value (current_node.chs) as mutable more than once at a time.
One solution is to derive the Clone trait for TrieNode. Clone is a common trait for the ability to explicitly duplicate an object:
#[derive(Debug, Clone)]
struct TrieNode {
chs: HashMap<char, TrieNode>,
value: Option<i32>,
}
Now instead of borrowing self.root, you can clone it:
fn delete(&mut self, key: &String) -> Option<i32> {
if key.is_empty() {
return None
}
// clone `self.root`
let mut current_node = self.root.clone();
for (ind, ch) in key.chars().enumerate() {
match current_node.chs.get_mut(&ch) {
Some(node) => {
if ind < key.len() - 1 {
// clone `node`
current_node = node.clone();
}
// ...
If performance is an issue, then cloning is probably not the best idea. However, it is still an option and may or may not suit your use case.

Difference between two Iterator<Range<usize>>'s

My program represents sets as Iterator<Range<usize>>, and I'm trying to implement set subtraction.
Essentially, I'm trying to create a function set_diff such that:
let a = vec![1..5, 7..10];
let a = a.into_iter();
let b = vec![3..9];
let b = b.into_iter();
let mut c = set_diff(a, b);
assert_eq!(c.next(), Some(1..3));
assert_eq!(c.next(), Some(9..10));
assert_eq!(c.next(), None);
This is complicated by the fact that this code should run with #[no_std]. The real iterators a and b are able to be cloned, if that helps.
I've made a probably-working iterator for the difference of two ranges, below. The only possible solution I've thought of would be to flatmap this over each element of A for every element in B, but that's really inefficient.
use std::cmp::{max, min};
use std::ops::Range;
/// An extension for Ranges allowing subtraction.
pub trait RangeExt<T: Ord> {
fn difference(self, other: Self) -> DiffIter<T>;
}
impl RangeExt<usize> for Range<usize> {
fn difference(self, other: Range<usize>) -> DiffIter<usize> {
DiffIter {
state: Some(match (self.start < other.start, self.end < other.end) {
(false, false) => DiffIterState::One(Range {
start: max(other.end, self.start),
end: self.end,
}),
(false, true) => DiffIterState::None,
(true, false) => DiffIterState::Two(Range {
start: self.start,
end: other.start,
}, Range {
start: other.end,
end: self.end,
}),
(true, true) => DiffIterState::One(Range {
start: self.start,
end: if other.start == self.end {
self.end
} else {
min(other.start - 1, self.end)
}
}),
})
}
}
}
/// A iterator for the difference of two ranges.
pub struct DiffIter<T> {
state: Option<DiffIterState<T>>,
}
impl<T> Iterator for DiffIter<T> {
type Item = Range<T>;
fn next(&mut self) -> Option<Range<T>> {
let (out, next) = match self.state.take().unwrap() {
DiffIterState::None => {
(None, DiffIterState::None)
},
DiffIterState::One(r) => {
(Some(r), DiffIterState::None)
},
DiffIterState::Two(l, r) => {
(Some(l), DiffIterState::One(r))
},
};
self.state = Some(next);
out
}
}
enum DiffIterState<T> {
None,
One(Range<T>),
Two(Range<T>, Range<T>),
}

Modifying a value inside an enum while matching

Is it possible to directly modify a value embedded inside an enum?
The following fails with error: cannot borrow immutable anonymous field `a.0` as mutable, even though I used ref mut.
enum Foo {
Bar(usize),
}
fn main() {
let a = Foo::Bar(10);
match a {
Foo::Bar(ref mut val) => *val = 33,
}
match a {
Foo::Bar(val) => println!("{}", val), // should print 33
}
}
That's not a huge problem because I can do the following as a work-around:
match a {
Foo::Bar(val) => a = Foo::Bar(33),
}
But is this the correct way?
You need to make the binding to a mutable.
enum Foo {
Bar(usize),
}
fn main() {
let mut a = Foo::Bar(10);
match a {
Foo::Bar(ref mut val) => *val = 33,
}
match a {
Foo::Bar(val) => println!("{}", val), // 33
}
}

Cannot move out of borrowed content when matching an enum

I'm trying to print out a tree (it's a LinkedList right now, but that will be fixed):
use std::io;
use std::rc::Rc;
enum NodeKind {
Branch(Rc<Node>),
Leaf,
}
struct Node {
value: i32,
kind: NodeKind,
}
fn main() {
let leaf = Node { value: 10, kind: NodeKind::Leaf };
let branch = Node { value: 50, kind: NodeKind::Branch(Rc::new(leaf)) };
let root = Node { value: 100, kind: NodeKind::Branch(Rc::new(branch)) };
let mut current = root;
while true {
println!("{}", current.value);
match current.kind {
NodeKind::Branch(next) => {
current = *next;
}
NodeKind::Leaf => {
break;
}
}
}
let mut reader = io::stdin();
let buff = &mut String::new();
let read = reader.read_line(buff);
}
The compiler says:
error[E0507]: cannot move out of borrowed content
--> src/main.rs:24:27
|
24 | current = *next;
| ^^^^^ cannot move out of borrowed content
I'm reading the value only, not changing anything. I'm assigning a value from a reference to another value, trying to dereference an Rc<T> value and store it in a local mut variable.
maybe something like this may work:
while true {
println!("{}", current.value);
match &current.kind {
&NodeKind::Branch(next) => {
current = next;
}
&NodeKind::Leaf => {
break;
}
}
}
or maybe
let mut current = &Rc::new(root);
while true {
println!("{}", current.value);
match current.kind {
NodeKind::Branch(next) => {
current = &next;
}
NodeKind::Leaf => {
break;
}
}
}
but I get the same error plus 'next' does not live long enough
There is no need to clone here, it is absolutely possible to do what you want to achieve with references:
use std::rc::Rc;
enum NodeKind {
Branch(Rc<Node>),
Leaf,
}
struct Node {
value: i32,
kind: NodeKind,
}
fn main() {
let leaf = Node { value: 10, kind: NodeKind::Leaf };
let branch = Node { value: 50, kind: NodeKind::Branch(Rc::new(leaf)) };
let root = Node { value: 100, kind: NodeKind::Branch(Rc::new(branch)) };
let mut current = &root;
loop {
println!("{}", current.value);
match current.kind {
NodeKind::Branch(ref next) => {
current = &**next;
}
NodeKind::Leaf => break,
}
}
}
The only important changes from your code is that the pattern in the match is ref next and current is of type &Node.
ref patterns bind their variables by reference, that is, next has type &Rc<Node>. To get &Node from it, you need to dereference it two times to get Node and then reference again to get &Node. Due to Deref coercions, it is also possible to write current = &next, and the compiler will insert an appropriate number of *s for you automatically.
I also changed from while (true) to loop because it is more idiomatic and it helps the compiler to reason about your code.
All traversals of tree-like structures are done like this in Rust. ref patterns allow not to move out of variables, which is absolutely necessary when you only need to read data. You can find more about patterns and how they interact with ownership and borrowing here.
The error is displayed because by default match will perform a move.
After a value is moved (i.e. wasn't taken by reference or method that takes self was called) subsequent calls fail. You'll probably need to clone, which is a property both of your struct and enum lack. Once you add those (#[derive(Clone)) and change current = *next; into current = (*next).clone();, your program will work again!
use std::io;
use std::rc::Rc;
#[derive(Clone)]
enum NodeKind {
Branch(Rc<Node>),
Leaf,
}
#[derive(Clone)]
struct Node {
value: i32,
kind: NodeKind,
}
fn main() {
let leaf = Node { value: 10, kind: NodeKind::Leaf };
let branch = Node { value: 50, kind: NodeKind::Branch(std::rc::Rc::new(leaf)) };
let root = Node { value: 100, kind: NodeKind::Branch(std::rc::Rc::new(branch)) };
let mut current = root;
while true {
println!("{}", current.value);
match current.kind {
NodeKind::Branch(next) => {
current = (*next).clone();
}
NodeKind::Leaf => {
break;
}
}
}
let reader = io::stdin();
let buff = &mut String::new();
let read = reader.read_line(buff);
}
Playground
If you let mut current = &root then you can avoid clone() as per Vladimir's response below (playpen of Vladimir's version).
I can't figure out the issue with 1) yet, but I did find an answer for 2).
At the top, you need to use:
use std::rc::Rc;
instead of
use std::rc;

Resources