Bird
Raised Fist0
DSA Rustprogramming~10 mins

Graph vs Tree Key Structural Difference in DSA Rust - Interactive Comparison Practice

Choose your learning style10 modes available
Practice - 5 Tasks
Answer the questions below
1fill in blank
easy

Complete the code to check if a graph has cycles.

DSA Rust
fn has_cycle(graph: &Vec<Vec<usize>>) -> bool {
    let mut visited = vec![false; graph.len()];
    for node in 0..graph.len() {
        if !visited[node] && dfs(node, graph, &mut visited, [1]) {
            return true;
        }
    }
    false
}

fn dfs(node: usize, graph: &Vec<Vec<usize>>, visited: &mut Vec<bool>, parent: usize) -> bool {
    visited[node] = true;
    for &neighbor in &graph[node] {
        if !visited[neighbor] {
            if dfs(neighbor, graph, visited, node) {
                return true;
            }
        } else if neighbor != parent {
            return true;
        }
    }
    false
}
Drag options to blanks, or click blank then click option'
Anode
Bgraph.len()
C0
Dusize::MAX
Attempts:
3 left
💡 Hint
Common Mistakes
Using 0 as parent causes false cycle detection at root.
Using node itself causes incorrect logic.
2fill in blank
medium

Complete the code to add an edge in an undirected graph.

DSA Rust
fn add_edge(graph: &mut Vec<Vec<usize>>, u: usize, v: usize) {
    graph[u].push([1]);
    graph[v].push(u);
}
Drag options to blanks, or click blank then click option'
Av
Bu
Cgraph.len()
D0
Attempts:
3 left
💡 Hint
Common Mistakes
Adding the wrong node index to adjacency list.
Forgetting to add edge in both directions.
3fill in blank
hard

Fix the error in the code that checks if a tree is connected.

DSA Rust
fn is_connected(graph: &Vec<Vec<usize>>) -> bool {
    let mut visited = vec![false; graph.len()];
    dfs(0, graph, &mut visited);
    visited.iter().[1](|&v| v)
}

fn dfs(node: usize, graph: &Vec<Vec<usize>>, visited: &mut Vec<bool>) {
    visited[node] = true;
    for &neighbor in &graph[node] {
        if !visited[neighbor] {
            dfs(neighbor, graph, visited);
        }
    }
}
Drag options to blanks, or click blank then click option'
Aany
Bfind
Call
Dfilter
Attempts:
3 left
💡 Hint
Common Mistakes
Using any returns true if any node is visited, not all.
Using find or filter returns iterators, not booleans.
4fill in blank
hard

Fill both blanks to create a function that counts edges in an undirected graph.

DSA Rust
fn count_edges(graph: &Vec<Vec<usize>>) -> usize {
    let mut count = 0;
    for neighbors in graph.iter() {
        count += neighbors.[1]();
    }
    count [2] 2
}
Drag options to blanks, or click blank then click option'
Alen
B/
C*
Dsum
Attempts:
3 left
💡 Hint
Common Mistakes
Multiplying instead of dividing causes wrong count.
Using sum on neighbors (which are vectors) causes error.
5fill in blank
hard

Fill all three blanks to create a function that builds a tree from edges and checks if it has cycles.

DSA Rust
fn build_tree_and_check_cycle(n: usize, edges: &Vec<(usize, usize)>) -> bool {
    let mut graph = vec![Vec::new(); n];
    for &(u, v) in edges {
        graph[u].push([1]);
        graph[v].push([2]);
    }
    let mut visited = vec![false; n];
    for node in 0..n {
        if !visited[node] && dfs(node, &graph, &mut visited, [3]) {
            return true;
        }
    }
    false
}

fn dfs(node: usize, graph: &Vec<Vec<usize>>, visited: &mut Vec<bool>, parent: usize) -> bool {
    visited[node] = true;
    for &neighbor in &graph[node] {
        if !visited[neighbor] {
            if dfs(neighbor, graph, visited, node) {
                return true;
            }
        } else if neighbor != parent {
            return true;
        }
    }
    false
}
Drag options to blanks, or click blank then click option'
Av
Bu
Cusize::MAX
D0
Attempts:
3 left
💡 Hint
Common Mistakes
Swapping u and v in adjacency lists.
Using 0 as initial parent causes false positives.

Practice

(1/5)
1. Which of the following is a key structural difference between a graph and a tree?
easy
A. A tree has no cycles, but a graph can have cycles.
B. A graph always has a root node, but a tree does not.
C. A tree can have multiple edges between the same nodes, but a graph cannot.
D. A graph is always directed, but a tree is always undirected.

Solution

  1. Step 1: Understand cycle presence in trees and graphs

    Trees are acyclic by definition, meaning they do not contain any cycles. Graphs can have cycles or be acyclic.
  2. Step 2: Analyze other options for correctness

    Graphs do not always have a root node; trees do have a root. Multiple edges can exist in graphs (multigraphs), but trees do not have multiple edges between the same nodes. Both graphs and trees can be directed or undirected.
  3. Final Answer:

    A tree has no cycles, but a graph can have cycles. -> Option A
  4. Quick Check:

    Cycle presence = Tree no, Graph yes [OK]
Hint: Trees never have cycles; graphs can have cycles [OK]
Common Mistakes:
  • Thinking graphs always have a root node
  • Believing trees can have cycles
  • Confusing directionality rules
2. Which Rust code snippet correctly declares a tree node struct with a parent and children?
easy
A. struct TreeNode { parent: Option<TreeNode>, children: Vec }
B. struct TreeNode { parent: TreeNode, children: Vec<TreeNode> }
C. struct TreeNode { parent: Box<TreeNode>, children: Vec<TreeNode> }
D. struct TreeNode { parent: Option, children: Vec }

Solution

  1. Step 1: Understand ownership and optional parent in Rust

    Parent can be None (root node), so Option is needed. Box is used for heap allocation to avoid recursive size issues.
  2. Step 2: Check children vector type

    Children are multiple nodes, so Vec is correct to hold multiple heap-allocated nodes.
  3. Final Answer:

    struct TreeNode { parent: Option, children: Vec } -> Option D
  4. Quick Check:

    Use Option and Box for recursive tree nodes [OK]
Hint: Use Option for optional recursive fields in Rust [OK]
Common Mistakes:
  • Using direct TreeNode type causing infinite size error
  • Not using Option for nullable parent
  • Using Vec<TreeNode> without Box causing stack overflow
3. Given the following Rust code representing a graph adjacency list, what is the output of printing the neighbors of node 1?
let graph = vec![
    vec![1, 2],
    vec![0, 3],
    vec![0],
    vec![1]
];
println!("{:?}", graph[1]);
medium
A. [0, 3]
B. [1, 2]
C. [1, 3]
D. [0, 1]

Solution

  1. Step 1: Identify neighbors of node 1 in adjacency list

    graph[1] is the second element: vec![0, 3], meaning node 1 connects to nodes 0 and 3.
  2. Step 2: Confirm printed output matches neighbors

    Printing graph[1] outputs [0, 3].
  3. Final Answer:

    [0, 3] -> Option A
  4. Quick Check:

    Neighbors of node 1 = [0, 3] [OK]
Hint: Index adjacency list by node number to get neighbors [OK]
Common Mistakes:
  • Confusing node indices and neighbors
  • Printing wrong vector index
  • Misreading vector contents
4. Consider this Rust code snippet for a tree structure:
struct Node {
    value: i32,
    children: Vec<Node>,
}

fn add_child(parent: &mut Node, child: Node) {
    parent.children.push(child);
}

fn main() {
    let mut root = Node { value: 1, children: vec![] };
    let child = Node { value: 2, children: vec![] };
    add_child(&mut root, child);
    println!("{}", root.children[0].value);
}
What error will this code produce?
medium
A. Compilation error due to recursive struct size
B. Compilation error due to borrowing rules
C. No error; prints 2
D. Runtime panic due to index out of bounds

Solution

  1. Step 1: Analyze struct and function usage

    Node struct holds children as Vec<Node>, which is allowed because Vec is heap allocated. add_child pushes child correctly.
  2. Step 2: Check main function behavior

    Root node is mutable, child is created and added. Printing root.children[0].value prints 2 without error.
  3. Final Answer:

    No error; prints 2 -> Option C
  4. Quick Check:

    Vec<Node> allows recursive tree; code runs fine [OK]
Hint: Vec stores heap data; recursive structs allowed [OK]
Common Mistakes:
  • Expecting recursive struct size error without Box
  • Confusing borrowing errors
  • Assuming runtime panic on valid index
5. You want to represent a directed acyclic graph (DAG) in Rust and ensure it has no cycles. Which approach best enforces the key structural difference from a tree?
hard
A. Use a tree struct with parent pointers and children vectors, disallowing cycles by design.
B. Use a graph adjacency list with cycle detection logic during edge insertion.
C. Use a graph with multiple edges allowed and no cycle checks.
D. Use a tree struct but allow cycles by linking nodes arbitrarily.

Solution

  1. Step 1: Understand DAG vs Tree structure

    DAGs allow multiple parents but no cycles. Trees have exactly one parent per node except root.
  2. Step 2: Evaluate approaches for cycle prevention

    Using adjacency list with cycle detection on edge insertion ensures no cycles, fitting DAG definition. Trees disallow multiple parents, so not suitable for DAGs.
  3. Final Answer:

    Use a graph adjacency list with cycle detection logic during edge insertion. -> Option B
  4. Quick Check:

    DAG = graph + cycle check [OK]
Hint: Detect cycles on insert to keep DAG acyclic [OK]
Common Mistakes:
  • Confusing trees with DAGs
  • Ignoring cycle detection in graphs
  • Allowing cycles in supposed DAG
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard