📖 Scenario: Imagine you are managing a line of customers waiting to buy tickets. You want to add new customers to the end of the line efficiently. This line is represented using a linked list.
🎯 Goal: You will build a simple linked list in Rust and add a new element to the end of the list (enqueue operation).
📋 What You'll Learn
Create a linked list node struct called Node with a value and a next pointer
Create a linked list struct called LinkedList with a head pointer
Add a method enqueue to add a new node at the end of the list
Print the linked list values after enqueue operation
💡 Why This Matters
🌍 Real World
Linked lists are used in real-world applications like task scheduling, undo functionality in editors, and managing dynamic data where size changes frequently.
💼 Career
Understanding linked lists and enqueue operations is fundamental for software developers working with data structures, memory management, and system design.
Progress0 / 4 steps
1
Create the Node and LinkedList structs
Create a struct called Node with a field value: i32 and a field next: Option>. Also create a struct called LinkedList with a field head: Option>.
DSA Rust
Hint
Use Option> for the next pointer to allow for empty or next nodes.
2
Add a new method enqueue to LinkedList
Add an impl block for LinkedList and write a method called enqueue that takes &mut self and a parameter value: i32. Inside the method, create a new Node with the given value and next set to None.
DSA Rust
Hint
Use Box::new(Node { value, next: None }) to create the new node.
3
Complete enqueue to add node at the end
Inside the enqueue method, check if self.head is None. If yes, set self.head to Some(new_node). Otherwise, use a mutable reference to traverse the list until you find the last node (where next is None) and set its next to Some(new_node).
DSA Rust
Hint
Use as_mut().unwrap() to get a mutable reference to the current node.
4
Print the linked list after enqueue
Write a print_list method inside impl LinkedList that prints all values in the list separated by -> and ending with None. Then create a main function, create a LinkedList instance, enqueue the values 10, 20, and 30, and call print_list.
DSA Rust
Hint
Use a while let Some(node) = current loop to traverse and print the list.
Practice
(1/5)
1. What does the enqueue operation do in a linked list implementation of a queue?
easy
A. Adds a new element at the beginning (head) of the linked list
B. Removes the first element from the linked list
C. Adds a new element at the end (tail) of the linked list
D. Deletes the last element from the linked list
Solution
Step 1: Understand enqueue operation in queue
Enqueue means adding an element to the queue, which is done at the end (tail) in a linked list.
Step 2: Identify linked list position for enqueue
In a linked list queue, new nodes are added at the tail to maintain FIFO order.
Final Answer:
Adds a new element at the end (tail) of the linked list -> Option C
Quick Check:
Enqueue = Add at tail [OK]
Hint: Enqueue always adds at the tail in linked list queue [OK]
Common Mistakes:
Confusing enqueue with dequeue operation
Adding new element at head instead of tail
Thinking enqueue removes elements
2. Which of the following Rust code snippets correctly enqueues a new node with value val into a linked list queue?
easy
A. let new_node = Box::new(Node { data: val, next: None }); tail.next = Some(new_node); tail = tail.next.as_mut().unwrap();
B. let new_node = Box::new(Node { data: val, next: None }); head = Some(new_node);
C. let new_node = Box::new(Node { data: val, next: head }); head = Some(new_node);
D. let new_node = Box::new(Node { data: val, next: None }); tail = Some(new_node);
Solution
Step 1: Create new node with value and no next
The new node is created with data = val and next = None, correct for enqueue at tail.
Step 2: Link new node at tail and update tail pointer
Setting tail.next to new_node and moving tail pointer to new_node is correct enqueue logic.
Final Answer:
let new_node = Box::new(Node { data: val, next: None }); tail.next = Some(new_node); tail = tail.next.as_mut().unwrap(); -> Option A
Quick Check:
Enqueue = add at tail and update tail [OK]
Hint: Enqueue updates tail.next and tail pointer [OK]
Common Mistakes:
Assigning new node to head instead of tail
Not updating tail pointer after enqueue
Linking new node's next to head (wrong for enqueue)
3. Given this Rust code snippet for enqueue operation on a linked list queue, what will be the printed queue after enqueuing values 10, 20, 30?
D. Assigning tail pointer to reference of new_node which is dropped after function ends
Solution
Step 1: Analyze new_node lifetime
new_node is a local variable and will be dropped after function ends, so tail pointer becomes invalid.
Step 2: Understand pointer assignment issue
Assigning tail to &mut *new_node stores pointer to dropped memory, causing undefined behavior.
Final Answer:
Assigning tail pointer to reference of new_node which is dropped after function ends -> Option D
Quick Check:
Pointer to dropped node causes bug [OK]
Hint: Tail must point to heap node, not local variable [OK]
Common Mistakes:
Using local variable reference for tail pointer
Ignoring unsafe pointer lifetime issues
Not updating tail pointer at all
5. You want to implement a queue using a singly linked list in Rust that supports enqueue and dequeue efficiently. Which approach correctly handles enqueue operation to maintain O(1) time complexity and safe memory management?
A) Add new node at head and update head pointer.
B) Add new node at tail, update tail pointer, and use Option for next pointers.
C) Add new node at tail but do not update tail pointer.
D) Add new node at head and update tail pointer.
hard
A. Add new node at tail, update tail pointer, and use Option for next pointers.
B. Add new node at head and update head pointer.
C. Add new node at tail but do not update tail pointer.
D. Add new node at head and update tail pointer.
Solution
Step 1: Understand enqueue efficiency in linked list queue
Enqueue must add at tail and update tail pointer to keep O(1) time complexity.
Step 2: Use Option for safe memory management
Using Option for next pointers ensures ownership and safe heap allocation in Rust.
Step 3: Reject other options
Adding at head breaks FIFO order; not updating tail pointer breaks enqueue logic.
Final Answer:
Add new node at tail, update tail pointer, and use Option for next pointers. -> Option A
Quick Check:
Enqueue at tail + safe pointers = O(1) enqueue [OK]
Hint: Enqueue at tail with Option ensures O(1) and safety [OK]
Common Mistakes:
Adding at head breaks queue order
Not updating tail pointer after enqueue
Using raw pointers without ownership
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.