diff --git a/src/main/java/com/thealgorithms/datastructures/trees/BoundaryTraversal.java b/src/main/java/com/thealgorithms/datastructures/trees/BoundaryTraversal.java
new file mode 100644
index 000000000..9a79902cc
--- /dev/null
+++ b/src/main/java/com/thealgorithms/datastructures/trees/BoundaryTraversal.java
@@ -0,0 +1,168 @@
+package com.thealgorithms.datastructures.trees;
+
+import java.util.ArrayList;
+import java.util.Deque;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * BoundaryTraversal
+ *
+ * Start with the Root:
+ * Add the root node to the boundary list.
+ * Traverse the Left Boundary (Excluding Leaf Nodes):
+ * Move down the left side of the tree, adding each non-leaf node to the boundary list.
+ * If a node has a left child, go left; otherwise, go right.
+ * Visit All Leaf Nodes:
+ * Traverse the tree and add all leaf nodes to the boundary list, from left to right.
+ * Traverse the Right Boundary (Excluding Leaf Nodes) in Reverse Order:
+ * Move up the right side of the tree, adding each non-leaf node to a temporary list.
+ * If a node has a right child, go right; otherwise, go left.
+ * Reverse the temporary list and add it to the boundary list.
+ * Combine and Output:
+ * The final boundary list contains the root, left boundary, leaf nodes, and reversed right boundary in that order.
+ */
+public final class BoundaryTraversal {
+ private BoundaryTraversal() {
+ }
+
+ // Main function for boundary traversal, returns a list of boundary nodes in order
+ public static List boundaryTraversal(BinaryTree.Node root) {
+ List result = new ArrayList<>();
+ if (root == null) {
+ return result;
+ }
+
+ // Add root node if it's not a leaf node
+ if (!isLeaf(root)) {
+ result.add(root.data);
+ }
+
+ // Add left boundary
+ addLeftBoundary(root, result);
+
+ // Add leaf nodes
+ addLeaves(root, result);
+
+ // Add right boundary
+ addRightBoundary(root, result);
+
+ return result;
+ }
+
+ // Adds the left boundary, including nodes that have no left child but have a right child
+ private static void addLeftBoundary(BinaryTree.Node node, List result) {
+ BinaryTree.Node cur = node.left;
+
+ // If there is no left child but there is a right child, treat the right child as part of the left boundary
+ if (cur == null && node.right != null) {
+ cur = node.right;
+ }
+
+ while (cur != null) {
+ if (!isLeaf(cur)) {
+ result.add(cur.data); // Add non-leaf nodes to result
+ }
+ if (cur.left != null) {
+ cur = cur.left; // Move to the left child
+ } else if (cur.right != null) {
+ cur = cur.right; // If left child is null, move to the right child
+ } else {
+ break; // Stop if there are no children
+ }
+ }
+ }
+
+ // Adds leaf nodes (nodes without children)
+ private static void addLeaves(BinaryTree.Node node, List result) {
+ if (node == null) {
+ return;
+ }
+ if (isLeaf(node)) {
+ result.add(node.data); // Add leaf node
+ } else {
+ addLeaves(node.left, result); // Recur for left subtree
+ addLeaves(node.right, result); // Recur for right subtree
+ }
+ }
+
+ // Adds the right boundary, excluding leaf nodes
+ private static void addRightBoundary(BinaryTree.Node node, List result) {
+ BinaryTree.Node cur = node.right;
+ List temp = new ArrayList<>();
+
+ // If no right boundary is present and there is no left subtree, skip
+ if (cur != null && node.left == null) {
+ return;
+ }
+ while (cur != null) {
+ if (!isLeaf(cur)) {
+ temp.add(cur.data); // Store non-leaf nodes temporarily
+ }
+ if (cur.right != null) {
+ cur = cur.right; // Move to the right child
+ } else if (cur.left != null) {
+ cur = cur.left; // If right child is null, move to the left child
+ } else {
+ break; // Stop if there are no children
+ }
+ }
+
+ // Add the right boundary nodes in reverse order
+ for (int i = temp.size() - 1; i >= 0; i--) {
+ result.add(temp.get(i));
+ }
+ }
+
+ // Checks if a node is a leaf node
+ private static boolean isLeaf(BinaryTree.Node node) {
+ return node.left == null && node.right == null;
+ }
+
+ // Iterative boundary traversal
+ public static List iterativeBoundaryTraversal(BinaryTree.Node root) {
+ List result = new ArrayList<>();
+ if (root == null) {
+ return result;
+ }
+
+ // Add root node if it's not a leaf node
+ if (!isLeaf(root)) {
+ result.add(root.data);
+ }
+
+ // Handle the left boundary
+ BinaryTree.Node cur = root.left;
+ if (cur == null && root.right != null) {
+ cur = root.right;
+ }
+ while (cur != null) {
+ if (!isLeaf(cur)) {
+ result.add(cur.data); // Add non-leaf nodes to result
+ }
+ cur = (cur.left != null) ? cur.left : cur.right; // Prioritize left child, move to right if left is null
+ }
+
+ // Add leaf nodes
+ addLeaves(root, result);
+
+ // Handle the right boundary using a stack (reverse order)
+ cur = root.right;
+ Deque stack = new LinkedList<>();
+ if (cur != null && root.left == null) {
+ return result;
+ }
+ while (cur != null) {
+ if (!isLeaf(cur)) {
+ stack.push(cur.data); // Temporarily store right boundary nodes in a stack
+ }
+ cur = (cur.right != null) ? cur.right : cur.left; // Prioritize right child, move to left if right is null
+ }
+
+ // Add the right boundary nodes from the stack to maintain the correct order
+ while (!stack.isEmpty()) {
+ result.add(stack.pop());
+ }
+ return result;
+ }
+}
diff --git a/src/test/java/com/thealgorithms/datastructures/trees/BoundaryTraversalTest.java b/src/test/java/com/thealgorithms/datastructures/trees/BoundaryTraversalTest.java
new file mode 100644
index 000000000..515dac88c
--- /dev/null
+++ b/src/test/java/com/thealgorithms/datastructures/trees/BoundaryTraversalTest.java
@@ -0,0 +1,108 @@
+package com.thealgorithms.datastructures.trees;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.Collections;
+import java.util.List;
+import org.junit.jupiter.api.Test;
+
+/**
+ *
+ */
+public class BoundaryTraversalTest {
+
+ @Test
+ public void testNullRoot() {
+ assertEquals(Collections.emptyList(), BoundaryTraversal.boundaryTraversal(null));
+ assertEquals(Collections.emptyList(), BoundaryTraversal.iterativeBoundaryTraversal(null));
+ }
+
+ @Test
+ public void testSingleNodeTree() {
+ final BinaryTree.Node root = new BinaryTree.Node(1);
+
+ List expected = List.of(1);
+
+ assertEquals(expected, BoundaryTraversal.boundaryTraversal(root));
+ assertEquals(expected, BoundaryTraversal.iterativeBoundaryTraversal(root));
+ }
+
+ /*
+ 1
+ / \
+ 2 3
+ / \ / \
+ 4 5 6 7
+
+ */
+ @Test
+ public void testCompleteBinaryTree() {
+ final BinaryTree.Node root = TreeTestUtils.createTree(new Integer[] {1, 2, 3, 4, 5, 6, 7});
+
+ List expected = List.of(1, 2, 4, 5, 6, 7, 3);
+
+ assertEquals(expected, BoundaryTraversal.boundaryTraversal(root));
+ assertEquals(expected, BoundaryTraversal.iterativeBoundaryTraversal(root));
+ }
+
+ /*
+ 1
+ / \
+ 2 7
+ / \
+ 3 8
+ \ /
+ 4 9
+ / \
+ 5 6
+ / \
+ 10 11
+ */
+ @Test
+ public void testBoundaryTraversal() {
+ final BinaryTree.Node root = TreeTestUtils.createTree(new Integer[] {1, 2, 7, 3, null, null, 8, null, 4, 9, null, 5, 6, 10, 11});
+
+ List expected = List.of(1, 2, 3, 4, 5, 6, 10, 11, 9, 8, 7);
+
+ assertEquals(expected, BoundaryTraversal.boundaryTraversal(root));
+ assertEquals(expected, BoundaryTraversal.iterativeBoundaryTraversal(root));
+ }
+
+ /*
+ 1
+ /
+ 2
+ /
+ 3
+ /
+ 4
+ */
+ @Test
+ public void testLeftSkewedTree() {
+ final BinaryTree.Node root = TreeTestUtils.createTree(new Integer[] {1, 2, null, 3, null, 4, null});
+
+ List expected = List.of(1, 2, 3, 4);
+
+ assertEquals(expected, BoundaryTraversal.boundaryTraversal(root));
+ assertEquals(expected, BoundaryTraversal.iterativeBoundaryTraversal(root));
+ }
+
+ /*
+ 5
+ \
+ 6
+ \
+ 7
+ \
+ 8
+ */
+ @Test
+ public void testRightSkewedTree() {
+ final BinaryTree.Node root = TreeTestUtils.createTree(new Integer[] {5, null, 6, null, 7, null, 8});
+
+ List expected = List.of(5, 6, 7, 8);
+
+ assertEquals(expected, BoundaryTraversal.boundaryTraversal(root));
+ assertEquals(expected, BoundaryTraversal.iterativeBoundaryTraversal(root));
+ }
+}