Skip to content

Commit 90a66df

Browse files
williamfisetclaude
andauthored
Refactor RootingTree: add docs, final fields, and tree diagrams (williamfiset#1287)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent e8511ed commit 90a66df

1 file changed

Lines changed: 44 additions & 24 deletions

File tree

  • src/main/java/com/williamfiset/algorithms/graphtheory/treealgorithms

src/main/java/com/williamfiset/algorithms/graphtheory/treealgorithms/RootingTree.java

Lines changed: 44 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,26 @@
11
/**
2-
* Often when working with trees we are given them as a graph with undirected edges, however
3-
* sometimes a better representation is a rooted tree.
2+
* Rooting an Undirected Tree
43
*
5-
* <p>Time Complexity: O(V+E)
4+
* Given an undirected tree as an adjacency list, this algorithm converts it
5+
* into a rooted tree by performing a DFS from a chosen root node. Each node
6+
* in the resulting tree stores its parent and children.
7+
*
8+
* Time: O(V + E)
9+
* Space: O(V)
610
*
711
* @author William Fiset, william.alexandre.fiset@gmail.com
812
*/
913
package com.williamfiset.algorithms.graphtheory.treealgorithms;
1014

11-
import java.util.*;
15+
import java.util.ArrayList;
16+
import java.util.List;
1217

1318
public class RootingTree {
1419

1520
public static class TreeNode {
16-
private int id;
17-
private TreeNode parent;
18-
private List<TreeNode> children;
21+
private final int id;
22+
private final TreeNode parent;
23+
private final List<TreeNode> children;
1924

2025
// Useful constructor for root node.
2126
public TreeNode(int id) {
@@ -25,7 +30,7 @@ public TreeNode(int id) {
2530
public TreeNode(int id, TreeNode parent) {
2631
this.id = id;
2732
this.parent = parent;
28-
children = new LinkedList<>();
33+
this.children = new ArrayList<>();
2934
}
3035

3136
public void addChildren(TreeNode... nodes) {
@@ -66,43 +71,63 @@ public int hashCode() {
6671
}
6772
}
6873

74+
/**
75+
* Roots the undirected tree at the given node and returns the root TreeNode.
76+
*/
6977
public static TreeNode rootTree(List<List<Integer>> graph, int rootId) {
7078
TreeNode root = new TreeNode(rootId);
7179
return buildTree(graph, root);
7280
}
7381

74-
// Do dfs to construct rooted tree.
82+
/**
83+
* Recursively builds the rooted tree via DFS. Skips the edge back to the
84+
* parent to avoid cycles.
85+
*/
7586
private static TreeNode buildTree(List<List<Integer>> graph, TreeNode node) {
7687
for (int childId : graph.get(node.id())) {
77-
// Ignore adding an edge pointing back to parent.
88+
// Ignore the edge pointing back to parent.
7889
if (node.parent() != null && childId == node.parent().id()) {
7990
continue;
8091
}
81-
8292
TreeNode child = new TreeNode(childId, node);
8393
node.addChildren(child);
84-
8594
buildTree(graph, child);
8695
}
8796
return node;
8897
}
8998

90-
/** ********** TESTING ********* */
99+
/* Graph helpers */
91100

92-
// Create a graph as a adjacency list
93-
private static List<List<Integer>> createGraph(int n) {
101+
public static List<List<Integer>> createGraph(int n) {
94102
List<List<Integer>> graph = new ArrayList<>(n);
95-
for (int i = 0; i < n; i++) graph.add(new LinkedList<>());
103+
for (int i = 0; i < n; i++) graph.add(new ArrayList<>());
96104
return graph;
97105
}
98106

99-
private static void addUndirectedEdge(List<List<Integer>> graph, int from, int to) {
107+
public static void addUndirectedEdge(List<List<Integer>> graph, int from, int to) {
100108
graph.get(from).add(to);
101109
graph.get(to).add(from);
102110
}
103111

112+
// ==================== Main ====================
113+
104114
public static void main(String[] args) {
105115

116+
// Undirected tree:
117+
//
118+
// 0 - 1 - 2 - 3 - 4
119+
// | |
120+
// 6 5
121+
// / \
122+
// 7 8
123+
//
124+
// Rooted at 6:
125+
//
126+
// 6
127+
// 2 7 8
128+
// 1 3
129+
// 0 4 5
130+
106131
List<List<Integer>> graph = createGraph(9);
107132
addUndirectedEdge(graph, 0, 1);
108133
addUndirectedEdge(graph, 2, 1);
@@ -113,12 +138,6 @@ public static void main(String[] args) {
113138
addUndirectedEdge(graph, 6, 7);
114139
addUndirectedEdge(graph, 6, 8);
115140

116-
// Rooted at 6 the tree should look like:
117-
// 6
118-
// 2 7 8
119-
// 1 3
120-
// 0 4 5
121-
122141
TreeNode root = rootTree(graph, 6);
123142

124143
// Layer 0: [6]
@@ -136,7 +155,8 @@ public static void main(String[] args) {
136155
+ ", "
137156
+ root.children.get(0).children.get(1).children);
138157

139-
// Rooted at 3 the tree should look like:
158+
// Rooted at 3:
159+
//
140160
// 3
141161
// 2 4 5
142162
// 6 1

0 commit comments

Comments
 (0)