From a391ecf04fe7b3bf38f79d8ce5abf149e111de5f Mon Sep 17 00:00:00 2001 From: Marcos Date: Thu, 7 Dec 2017 23:37:09 +0100 Subject: [PATCH 1/3] BAEL-1339 - Implementing a binary tree in Java --- .../java/com/baeldung/tree/BinaryTree.java | 217 ++++++++++++++++++ .../com/baeldung/tree/BinaryTreeTest.java | 141 ++++++++++++ 2 files changed, 358 insertions(+) create mode 100644 core-java/src/main/java/com/baeldung/tree/BinaryTree.java create mode 100644 core-java/src/test/java/com/baeldung/tree/BinaryTreeTest.java diff --git a/core-java/src/main/java/com/baeldung/tree/BinaryTree.java b/core-java/src/main/java/com/baeldung/tree/BinaryTree.java new file mode 100644 index 0000000000..3c5f5f4e10 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/tree/BinaryTree.java @@ -0,0 +1,217 @@ +package com.baeldung.tree; + +import java.util.LinkedList; +import java.util.Queue; + +public class BinaryTree { + + Node root; + + public void add(int value) { + + Node newNode = new Node(value); + + if (root == null) { + root = newNode; + return; + } + + Node parent = root; + Node current = root; + + while (true) { + + if (newNode.value < parent.value) { + current = parent.left; + + if (current == null) { + parent.left = newNode; + break; + } + } else { + current = parent.right; + + if (current == null) { + parent.right = newNode; + break; + } + } + + parent = current; + } + + } + + public boolean isEmpty() { + return root == null; + } + + public boolean containsNode(int value) { + + Node current = root; + + while (current != null) { + + if (value == current.value) { + return true; + } + + if (value < current.value) { + current = current.left; + } else { + current = current.right; + } + + } + + return false; + } + + public void delete(int value) { + + Node current = root; + Node parent = root; + Node nodeToDelete = null; + boolean isLeftChild = false; + + while (nodeToDelete == null && current != null) { + + if (value == current.value) { + nodeToDelete = current; + } else if (value < current.value) { + parent = current; + current = current.left; + isLeftChild = true; + } else { + parent = current; + current = current.right; + isLeftChild = false; + } + + } + + if (nodeToDelete == null) { + return; + } + + // Case 1: no children + if (nodeToDelete.left == null && nodeToDelete.right == null) { + if (nodeToDelete == root) { + root = null; + } else if (isLeftChild) { + parent.left = null; + } else { + parent.right = null; + } + } + // Case 2: only 1 child + else if (nodeToDelete.right == null) { + if (nodeToDelete == root) { + root = nodeToDelete.left; + } else if (isLeftChild) { + parent.left = nodeToDelete.left; + } else { + parent.right = nodeToDelete.left; + } + } else if (nodeToDelete.left == null) { + if (nodeToDelete == root) { + root = nodeToDelete.right; + } else if (isLeftChild) { + parent.left = nodeToDelete.right; + } else { + parent.right = nodeToDelete.right; + } + } + // Case 3: 2 children + else if (nodeToDelete.left != null && nodeToDelete.right != null) { + Node replacement = findReplacement(nodeToDelete); + if (nodeToDelete == root) { + root = replacement; + } else if (isLeftChild) { + parent.left = replacement; + } else { + parent.right = replacement; + } + } + + } + + private Node findReplacement(Node nodeToDelete) { + + Node replacement = nodeToDelete; + Node parentReplacement = nodeToDelete; + Node current = nodeToDelete.right; + + while (current != null) { + parentReplacement = replacement; + replacement = current; + current = current.left; + } + + if (replacement != nodeToDelete.right) { + parentReplacement.left = replacement.right; + replacement.right = nodeToDelete.right; + } + + replacement.left = nodeToDelete.left; + + return replacement; + } + + public void traverseInOrder(Node node) { + if (node != null) { + traverseInOrder(node.left); + System.out.print(" " + node.value); + traverseInOrder(node.right); + } + } + + public void traversePreOrder(Node node) { + if (node != null) { + System.out.print(" " + node.value); + traversePreOrder(node.left); + traversePreOrder(node.right); + } + } + + public void traversePostOrder(Node node) { + if (node != null) { + traversePostOrder(node.left); + traversePostOrder(node.right); + + System.out.print(" " + node.value); + } + } + + public void traverseLevelOrder() { + Queue nodes = new LinkedList<>(); + nodes.add(root); + + while (!nodes.isEmpty()) { + + Node node = nodes.remove(); + + System.out.print(" " + node.value); + + if (node.left != null) { + nodes.add(node.left); + } + + if (node.left != null) { + nodes.add(node.right); + } + } + } + + class Node { + int value; + Node left; + Node right; + + Node(int value) { + this.value = value; + right = null; + left = null; + } + } +} diff --git a/core-java/src/test/java/com/baeldung/tree/BinaryTreeTest.java b/core-java/src/test/java/com/baeldung/tree/BinaryTreeTest.java new file mode 100644 index 0000000000..df0f3ba62d --- /dev/null +++ b/core-java/src/test/java/com/baeldung/tree/BinaryTreeTest.java @@ -0,0 +1,141 @@ +package com.baeldung.tree; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class BinaryTreeTest { + + @Test + public void givenABinaryTree_WhenAddElements_ThenTreeNotEmpty() { + + BinaryTree bt = new BinaryTree(); + + bt.add(6); + bt.add(4); + bt.add(8); + bt.add(3); + bt.add(5); + bt.add(7); + bt.add(9); + + assertTrue(!bt.isEmpty()); + } + + @Test + public void givenABinaryTree_WhenAddElements_ThenTreeContainsThoseElements() { + + BinaryTree bt = new BinaryTree(); + + bt.add(6); + bt.add(4); + bt.add(8); + bt.add(3); + bt.add(5); + bt.add(7); + bt.add(9); + + assertTrue(bt.containsNode(6)); + assertTrue(bt.containsNode(4)); + assertTrue(bt.containsNode(8)); + assertTrue(bt.containsNode(3)); + assertTrue(bt.containsNode(5)); + assertTrue(bt.containsNode(7)); + assertTrue(bt.containsNode(9)); + + assertFalse(bt.containsNode(1)); + assertFalse(bt.containsNode(10)); + } + + @Test + public void givenABinaryTree_WhenDeletingElements_ThenTreeDoesNotContainThoseElements() { + + BinaryTree bt = new BinaryTree(); + + bt.add(6); + bt.add(4); + bt.add(8); + bt.add(3); + bt.add(5); + bt.add(7); + bt.add(9); + + assertTrue(bt.containsNode(9)); + bt.delete(9); + assertFalse(bt.containsNode(9)); + + assertTrue(bt.containsNode(6)); + bt.delete(6); + assertFalse(bt.containsNode(6)); + + assertTrue(bt.containsNode(4)); + bt.delete(4); + assertFalse(bt.containsNode(4)); + } + + @Test + public void givenABinaryTree_WhenTraversingInOrder_ThenPrintValues() { + + BinaryTree bt = new BinaryTree(); + + bt.add(6); + bt.add(4); + bt.add(8); + bt.add(3); + bt.add(5); + bt.add(7); + bt.add(9); + + bt.traverseInOrder(bt.root); + } + + @Test + public void givenABinaryTree_WhenTraversingPreOrder_ThenPrintValues() { + + BinaryTree bt = new BinaryTree(); + + bt.add(6); + bt.add(4); + bt.add(8); + bt.add(3); + bt.add(5); + bt.add(7); + bt.add(9); + + bt.traversePreOrder(bt.root); + } + + @Test + public void givenABinaryTree_WhenTraversingPostOrder_ThenPrintValues() { + + BinaryTree bt = new BinaryTree(); + + bt.add(6); + bt.add(4); + bt.add(8); + bt.add(3); + bt.add(5); + bt.add(7); + bt.add(9); + + bt.traversePostOrder(bt.root); + } + + @Test + public void givenABinaryTree_WhenTraversingLevelOrder_ThenPrintValues() { + + BinaryTree bt = new BinaryTree(); + + bt.add(6); + bt.add(4); + bt.add(8); + bt.add(3); + bt.add(5); + bt.add(7); + bt.add(9); + + bt.traverseLevelOrder(); + } + +} From 7c82545377566c177690b86f401cbdada1adc9c7 Mon Sep 17 00:00:00 2001 From: Marcos Date: Sat, 9 Dec 2017 11:20:14 +0100 Subject: [PATCH 2/3] tests renaming --- core-java/src/test/java/com/baeldung/tree/BinaryTreeTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core-java/src/test/java/com/baeldung/tree/BinaryTreeTest.java b/core-java/src/test/java/com/baeldung/tree/BinaryTreeTest.java index df0f3ba62d..0b123a9684 100644 --- a/core-java/src/test/java/com/baeldung/tree/BinaryTreeTest.java +++ b/core-java/src/test/java/com/baeldung/tree/BinaryTreeTest.java @@ -8,7 +8,7 @@ import org.junit.Test; public class BinaryTreeTest { @Test - public void givenABinaryTree_WhenAddElements_ThenTreeNotEmpty() { + public void givenABinaryTree_WhenAddingElements_ThenTreeNotEmpty() { BinaryTree bt = new BinaryTree(); @@ -24,7 +24,7 @@ public class BinaryTreeTest { } @Test - public void givenABinaryTree_WhenAddElements_ThenTreeContainsThoseElements() { + public void givenABinaryTree_WhenAddingElements_ThenTreeContainsThoseElements() { BinaryTree bt = new BinaryTree(); From 72d162ddc99ca2f3d660d4d6be12e1c8e3e4bcac Mon Sep 17 00:00:00 2001 From: Marcos Date: Sun, 10 Dec 2017 19:27:45 +0100 Subject: [PATCH 3/3] tests refactoring --- .../java/com/baeldung/tree/BinaryTree.java | 1 - .../com/baeldung/tree/BinaryTreeTest.java | 82 +++---------------- 2 files changed, 13 insertions(+), 70 deletions(-) diff --git a/core-java/src/main/java/com/baeldung/tree/BinaryTree.java b/core-java/src/main/java/com/baeldung/tree/BinaryTree.java index 3c5f5f4e10..3cc496e348 100644 --- a/core-java/src/main/java/com/baeldung/tree/BinaryTree.java +++ b/core-java/src/main/java/com/baeldung/tree/BinaryTree.java @@ -39,7 +39,6 @@ public class BinaryTree { parent = current; } - } public boolean isEmpty() { diff --git a/core-java/src/test/java/com/baeldung/tree/BinaryTreeTest.java b/core-java/src/test/java/com/baeldung/tree/BinaryTreeTest.java index 0b123a9684..2c20c730df 100644 --- a/core-java/src/test/java/com/baeldung/tree/BinaryTreeTest.java +++ b/core-java/src/test/java/com/baeldung/tree/BinaryTreeTest.java @@ -10,15 +10,7 @@ public class BinaryTreeTest { @Test public void givenABinaryTree_WhenAddingElements_ThenTreeNotEmpty() { - BinaryTree bt = new BinaryTree(); - - bt.add(6); - bt.add(4); - bt.add(8); - bt.add(3); - bt.add(5); - bt.add(7); - bt.add(9); + BinaryTree bt = createBinaryTree(); assertTrue(!bt.isEmpty()); } @@ -26,66 +18,28 @@ public class BinaryTreeTest { @Test public void givenABinaryTree_WhenAddingElements_ThenTreeContainsThoseElements() { - BinaryTree bt = new BinaryTree(); - - bt.add(6); - bt.add(4); - bt.add(8); - bt.add(3); - bt.add(5); - bt.add(7); - bt.add(9); + BinaryTree bt = createBinaryTree(); assertTrue(bt.containsNode(6)); assertTrue(bt.containsNode(4)); - assertTrue(bt.containsNode(8)); - assertTrue(bt.containsNode(3)); - assertTrue(bt.containsNode(5)); - assertTrue(bt.containsNode(7)); - assertTrue(bt.containsNode(9)); assertFalse(bt.containsNode(1)); - assertFalse(bt.containsNode(10)); } @Test public void givenABinaryTree_WhenDeletingElements_ThenTreeDoesNotContainThoseElements() { - BinaryTree bt = new BinaryTree(); - - bt.add(6); - bt.add(4); - bt.add(8); - bt.add(3); - bt.add(5); - bt.add(7); - bt.add(9); + BinaryTree bt = createBinaryTree(); assertTrue(bt.containsNode(9)); bt.delete(9); assertFalse(bt.containsNode(9)); - - assertTrue(bt.containsNode(6)); - bt.delete(6); - assertFalse(bt.containsNode(6)); - - assertTrue(bt.containsNode(4)); - bt.delete(4); - assertFalse(bt.containsNode(4)); } @Test public void givenABinaryTree_WhenTraversingInOrder_ThenPrintValues() { - BinaryTree bt = new BinaryTree(); - - bt.add(6); - bt.add(4); - bt.add(8); - bt.add(3); - bt.add(5); - bt.add(7); - bt.add(9); + BinaryTree bt = createBinaryTree(); bt.traverseInOrder(bt.root); } @@ -93,15 +47,7 @@ public class BinaryTreeTest { @Test public void givenABinaryTree_WhenTraversingPreOrder_ThenPrintValues() { - BinaryTree bt = new BinaryTree(); - - bt.add(6); - bt.add(4); - bt.add(8); - bt.add(3); - bt.add(5); - bt.add(7); - bt.add(9); + BinaryTree bt = createBinaryTree(); bt.traversePreOrder(bt.root); } @@ -109,15 +55,7 @@ public class BinaryTreeTest { @Test public void givenABinaryTree_WhenTraversingPostOrder_ThenPrintValues() { - BinaryTree bt = new BinaryTree(); - - bt.add(6); - bt.add(4); - bt.add(8); - bt.add(3); - bt.add(5); - bt.add(7); - bt.add(9); + BinaryTree bt = createBinaryTree(); bt.traversePostOrder(bt.root); } @@ -125,6 +63,12 @@ public class BinaryTreeTest { @Test public void givenABinaryTree_WhenTraversingLevelOrder_ThenPrintValues() { + BinaryTree bt = createBinaryTree(); + + bt.traverseLevelOrder(); + } + + private BinaryTree createBinaryTree() { BinaryTree bt = new BinaryTree(); bt.add(6); @@ -135,7 +79,7 @@ public class BinaryTreeTest { bt.add(7); bt.add(9); - bt.traverseLevelOrder(); + return bt; } }