Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rust: How to implement linked list?

Tags:

rust

I thought I'd dive into Rust by imeplementing some very simple structure & algorithms, I started with a linked list. Turns out it's not actually that simple. This is my code so far:

enum List<T> 
{
    Node(T, ~List<T>),
    Nil
}

impl<T> List<T>
{
    fn new(vector: &[T]) -> List<T> { Nil }

    fn add(&mut self, item: T)
    {
        let tail = self;
        loop
        {
            match *tail
            {
                Node(_, ~ref next) => tail = next,
                Nil => break
            }
        }
        *tail = Node(item, ~Nil);
    }
}

This won't compile because next cannot be assigned to tail in the match statement due to incompatible mutability. I know this can easily be done using garbage collected pointers, but that kind of defeats the educational purpose of the exercise: I'd like to know how to do this without Gc or Rc pointers.

like image 836
kralyk Avatar asked Jan 16 '14 02:01

kralyk


People also ask

Does Rust have linked list?

It is difficult to implement Linked List in Rust as what is allowed in most languages is simply not allowed in Rust, While it may seem to be a little difficult but the Rust compiler also at the same time makes sure that your code is memory safe.

Why are linked lists so hard in Rust?

This is because Rust likes all of your memory to have one clear owner. And this means that cyclic data structures are unusually difficult compared to almost any other first program you might choose.

How are linked lists implemented in Ruby?

You have to start at the “head” of the list & follow the links until you find the node you want or until the end of the list. Removing (or adding) an item from the middle of a linked list is a lot faster. All you have to do is change the “next” pointer for one node.


1 Answers

It looks like you're trying to walk your own list to find the final element, but you don't actually have a loop. Assuming you fix that, your issue with mutability can be fixed by using ref mut instead of ref.

To try it myself I used a recursive implementation of add() and this works:

fn add(&mut self, item: T) {
    match *self {
        Node(_, ref mut next) => next.add(item),
        Nil => *self = Node(item, ~Nil)
    }
}

Offhand I'm not sure how to implement this using an iterative approach, due to issues with mutable borrowing.

like image 148
Lily Ballard Avatar answered Oct 13 '22 01:10

Lily Ballard