1
+ package com .thealgorithms .datastructures .trees ;
2
+
3
+ import java .util .*;
4
+
5
+ /**BoundaryTraversal
6
+ *
7
+ * Start with the Root:
8
+ * Add the root node to the boundary list.
9
+ * Traverse the Left Boundary (Excluding Leaf Nodes):
10
+ * Move down the left side of the tree, adding each non-leaf node to the boundary list.
11
+ * If a node has a left child, go left; otherwise, go right.
12
+ * Visit All Leaf Nodes:
13
+ * Traverse the tree and add all leaf nodes to the boundary list, from left to right.
14
+ * Traverse the Right Boundary (Excluding Leaf Nodes) in Reverse Order:
15
+ * Move up the right side of the tree, adding each non-leaf node to a temporary list.
16
+ * If a node has a right child, go right; otherwise, go left.
17
+ * Reverse the temporary list and add it to the boundary list.
18
+ * Combine and Output:
19
+ * The final boundary list contains the root, left boundary, leaf nodes, and reversed right boundary in that order.
20
+ */
21
+ public final class BoundaryTraversal {
22
+ private BoundaryTraversal () {}
23
+
24
+ // Main function for boundary traversal, returns a list of boundary nodes in order
25
+ public static List <Integer > boundaryTraversal (BinaryTree .Node root ) {
26
+ List <Integer > result = new ArrayList <>();
27
+ if (root == null ) {
28
+ return result ;
29
+ }
30
+
31
+ // Add root node if it's not a leaf node
32
+ if (!isLeaf (root )) {
33
+ result .add (root .data );
34
+ }
35
+
36
+ // Add left boundary
37
+ addLeftBoundary (root , result );
38
+
39
+ // Add leaf nodes
40
+ addLeaves (root , result );
41
+
42
+ // Add right boundary
43
+ addRightBoundary (root , result );
44
+
45
+ return result ;
46
+ }
47
+
48
+ // Adds the left boundary, including nodes that have no left child but have a right child
49
+ private static void addLeftBoundary (BinaryTree .Node node , List <Integer > result ) {
50
+ BinaryTree .Node cur = node .left ;
51
+
52
+ // If there is no left child but there is a right child, treat the right child as part of the left boundary
53
+ if (cur == null && node .right != null ) {
54
+ cur = node .right ;
55
+ }
56
+
57
+ while (cur != null ) {
58
+ if (!isLeaf (cur )) {
59
+ result .add (cur .data ); // Add non-leaf nodes to result
60
+ }
61
+ if (cur .left != null ) {
62
+ cur = cur .left ; // Move to the left child
63
+ } else if (cur .right != null ) {
64
+ cur = cur .right ; // If left child is null, move to the right child
65
+ } else {
66
+ break ; // Stop if there are no children
67
+ }
68
+ }
69
+ }
70
+
71
+ // Adds leaf nodes (nodes without children)
72
+ private static void addLeaves (BinaryTree .Node node , List <Integer > result ) {
73
+ if (node == null ) {
74
+ return ;
75
+ }
76
+ if (isLeaf (node )) {
77
+ result .add (node .data ); // Add leaf node
78
+ } else {
79
+ addLeaves (node .left , result ); // Recur for left subtree
80
+ addLeaves (node .right , result ); // Recur for right subtree
81
+ }
82
+ }
83
+
84
+ // Adds the right boundary, excluding leaf nodes
85
+ private static void addRightBoundary (BinaryTree .Node node , List <Integer > result ) {
86
+ BinaryTree .Node cur = node .right ;
87
+ List <Integer > temp = new ArrayList <>();
88
+
89
+ // If no right boundary is present and there is no left subtree, skip
90
+ if (cur != null && node .left == null ) {
91
+ return ;
92
+ }
93
+ while (cur != null ) {
94
+ if (!isLeaf (cur )) {
95
+ temp .add (cur .data ); // Store non-leaf nodes temporarily
96
+ }
97
+ if (cur .right != null ) {
98
+ cur = cur .right ; // Move to the right child
99
+ } else if (cur .left != null ) {
100
+ cur = cur .left ; // If right child is null, move to the left child
101
+ } else {
102
+ break ; // Stop if there are no children
103
+ }
104
+ }
105
+
106
+ // Add the right boundary nodes in reverse order
107
+ for (int i = temp .size () - 1 ; i >= 0 ; i --) {
108
+ result .add (temp .get (i ));
109
+ }
110
+ }
111
+
112
+ // Checks if a node is a leaf node
113
+ private static boolean isLeaf (BinaryTree .Node node ) {
114
+ return (node .left == null && node .right == null );
115
+ }
116
+
117
+ // Iterative boundary traversal
118
+ public static List <Integer > iterativeBoundaryTraversal (BinaryTree .Node root ) {
119
+ List <Integer > result = new ArrayList <>();
120
+ if (root == null ) {
121
+ return result ;
122
+ }
123
+
124
+ // Add root node if it's not a leaf node
125
+ if (!isLeaf (root )) {
126
+ result .add (root .data );
127
+ }
128
+
129
+ // Handle the left boundary
130
+ BinaryTree .Node cur = root .left ;
131
+ if (cur == null && root .right != null ) {
132
+ cur = root .right ;
133
+ }
134
+ while (cur != null ) {
135
+ if (!isLeaf (cur )) {
136
+ result .add (cur .data ); // Add non-leaf nodes to result
137
+ }
138
+ cur = (cur .left != null ) ? cur .left : cur .right ; // Prioritize left child, move to right if left is null
139
+ }
140
+
141
+ // Add leaf nodes
142
+ addLeaves (root , result );
143
+
144
+ // Handle the right boundary using a stack (reverse order)
145
+ cur = root .right ;
146
+ Deque <Integer > stack = new LinkedList <>();
147
+ if (cur != null && root .left == null ) {
148
+ return result ;
149
+ }
150
+ while (cur != null ) {
151
+ if (!isLeaf (cur )) {
152
+ stack .push (cur .data ); // Temporarily store right boundary nodes in a stack
153
+ }
154
+ cur = (cur .right != null ) ? cur .right : cur .left ; // Prioritize right child, move to left if right is null
155
+ }
156
+
157
+ // Add the right boundary nodes from the stack to maintain the correct order
158
+ while (!stack .isEmpty ()) {
159
+ result .add (stack .pop ());
160
+ }
161
+ return result ;
162
+ }
163
+ }
0 commit comments