Tree vs Array vs Linked List When Hierarchy Matters in DSA Rust - Complexity Comparison
We want to understand how different data structures handle hierarchical data and how fast they work when we access or change elements.
Which structure is faster depends on how the data is organized and used.
Analyze the time complexity of searching for a value in different data structures representing hierarchy.
// Searching for a value in an array
fn search_array(arr: &[i32], target: i32) -> bool {
for &item in arr {
if item == target {
return true;
}
}
false
}
// Searching for a value in a linked list
struct Node {
value: i32,
next: Option>,
}
fn search_linked_list(head: &Option>, target: i32) -> bool {
let mut current = head;
while let Some(node) = current {
if node.value == target {
return true;
}
current = &node.next;
}
false
}
// Searching for a value in a tree (simple binary tree)
struct TreeNode {
value: i32,
left: Option>,
right: Option>,
}
fn search_tree(node: &Option>, target: i32) -> bool {
if let Some(n) = node {
if n.value == target {
return true;
}
search_tree(&n.left, target) || search_tree(&n.right, target)
} else {
false
}
}
This code shows how to find a value in an array, a linked list, and a tree representing hierarchical data.
Look at what repeats when searching:
- Primary operation: Checking each element or node's value.
- How many times:
- Array: Once per element, up to n times.
- Linked List: Once per node, up to n times.
- Tree: Visits nodes recursively, up to n times in worst case.
As the number of elements (n) grows, the search work grows roughly like this:
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | Up to 10 checks |
| 100 | Up to 100 checks |
| 1000 | Up to 1000 checks |
Pattern observation: The number of checks grows directly with the number of elements, doubling the data roughly doubles the work.
Time Complexity: O(n)
This means the search time grows linearly with the number of elements, no matter if it's an array, linked list, or tree in the worst case.
[X] Wrong: "Trees always search faster than arrays or linked lists because they are hierarchical."
[OK] Correct: If the tree is not balanced or organized for fast search, it can take as long as checking every node, just like arrays or lists.
Understanding how different data structures handle hierarchy and search helps you choose the right one and explain your choice clearly in interviews.
"What if the tree was a balanced binary search tree? How would the time complexity change?"
Practice
Solution
Step 1: Understand hierarchy representation
A hierarchy with multiple children per element needs a structure that can link one parent to many children.Step 2: Compare data structures
Arrays and linked lists are linear and do not naturally represent multiple children. Trees allow each node to have multiple children, fitting the hierarchy.Final Answer:
Tree -> Option DQuick Check:
Hierarchy with multiple children = Tree [OK]
- Choosing array for hierarchical data
- Using linked list which is linear
- Confusing stack with hierarchy
Solution
Step 1: Understand Rust linked list node
Linked list nodes need a pointer to the next node. Rust uses Option for nullable heap pointers.Step 2: Check each option
A uses direct Node which causes infinite size error. C uses reference without lifetime. D uses Vec which is for multiple children, not linked list.Final Answer:
struct Node { value: i32, next: Option } -> Option AQuick Check:
Linked list node uses Option [OK]
- Using direct Node type causing infinite size
- Using references without lifetimes
- Using Vec instead of single next pointer
struct Node {
value: i32,
children: Vec<Node>,
}
fn main() {
let child = Node { value: 10, children: vec![] };
let root = Node { value: 5, children: vec![child] };
println!("{}", root.children[0].value);
}Solution
Step 1: Understand tree structure and initialization
Root node has value 5 and one child with value 10 stored in a vector.Step 2: Trace the print statement
Printing root.children[0].value accesses the first child's value, which is 10.Final Answer:
10 -> Option AQuick Check:
root.children[0].value = 10 [OK]
- Printing root.value instead of child's
- Confusing vector index
- Assuming compilation error due to struct
struct Node {
value: i32,
next: Box<Node>,
}
fn main() {
let node = Node { value: 1, next: Box::new(Node { value: 2, next: Box::new(Node { value: 3, next: None }) }) };
}Solution
Step 1: Identify recursive type issue
Recursive types in Rust must use Option to allow end of list (None).Step 2: Check code for missing Option
Code uses Box<Node> without Option, so no way to represent end (None), causing compile error.Final Answer:
Missing Option for next pointer to allow None -> Option BQuick Check:
Recursive next pointer needs Option [OK]
- Thinking Box alone handles recursion
- Blaming i32 type
- Assuming syntax error in struct
Solution
Step 1: Understand file system hierarchy
Folders can contain files and other folders, so a recursive structure is needed.Step 2: Evaluate data structure options
Array or linked list can't represent nested folders well. HashMap stores flat keys, not hierarchy. Tree with enum Node allows files and folders recursively.Final Answer:
Tree with enum Node { File(String), Folder(Vec<Node>) } -> Option CQuick Check:
Recursive enum tree fits file system hierarchy [OK]
- Using flat arrays or lists for nested folders
- Using HashMap which is flat key-value
- Not using enum to distinguish files and folders
Ready to prove it?
Pass the test and this pattern moves unknown
