From 5b67340b354325d882574fcfd95f198e93a0842f Mon Sep 17 00:00:00 2001 From: kaitinghh <114789615+kaitinghh@users.noreply.github.com> Date: Fri, 29 Sep 2023 10:54:24 +0800 Subject: [PATCH 01/51] added ORS and tests --- build.gradle | 1 + .../oneDim/OrthogonalRangeSearching.java | 105 ++++++++++++++++++ .../oneDim/OrthogonalRangeSearchingTest.java | 41 +++++++ .../insertionSort/InsertionSortTest.java | 2 +- .../mergeSort/iterative/MergeSortTest.java | 2 +- .../mergeSort/recursive/MergeSortTest.java | 2 +- .../selectionSort/SelectionSortTest.java | 62 +++++------ 7 files changed, 180 insertions(+), 35 deletions(-) create mode 100644 src/main/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearching.java create mode 100644 src/test/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearchingTest.java diff --git a/build.gradle b/build.gradle index 0b5699ff..c67b79a7 100644 --- a/build.gradle +++ b/build.gradle @@ -25,6 +25,7 @@ repositories { dependencies { // Use JUnit test framework. testImplementation 'junit:junit:4.13.2' + testImplementation 'org.junit.jupiter:junit-jupiter:5.8.1' } java { diff --git a/src/main/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearching.java b/src/main/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearching.java new file mode 100644 index 00000000..c44cb668 --- /dev/null +++ b/src/main/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearching.java @@ -0,0 +1,105 @@ +package algorithms.orthogonalRangeSearching.oneDim; + +import algorithms.graphs.util.BinaryTreeNode; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.List; + +public class OrthogonalRangeSearching { + + public static BinaryTreeNode buildTree(int[] inputs, int start, int end) { + //build range tree from inputs + int mid = (end + start) / 2; + Arrays.sort(inputs); + + if (start > end) { + return null; + } else if (end - start + 1 > 3) { + return new BinaryTreeNode(inputs[mid], buildTree(inputs, start, mid), buildTree(inputs, mid + 1, end)); + } else if (end - start + 1 == 3) { + return new BinaryTreeNode(inputs[mid], buildTree(inputs, start, mid), new BinaryTreeNode(inputs[end])); + } else if (end - start + 1 == 2) { + return new BinaryTreeNode(inputs[mid], new BinaryTreeNode(inputs[start]), new BinaryTreeNode(inputs[end])); + } else { + return new BinaryTreeNode(inputs[mid]); + } + } + public static BinaryTreeNode findSplit(BinaryTreeNode root, int low, int high) { + BinaryTreeNode v = root; + + while (true) { + if (v == null) { + return null; + } else { + if (high <= v.getVal()) { + v = v.getLeft(); + } else if (low > v.getVal()) { + v = v.getRight(); + } else { + break; + } + } + } + return v; + } + + public static void allLeafTraversal(BinaryTreeNode v, List result) { + if (v != null) { + if (v.getLeft() != null) { + allLeafTraversal(v.getLeft(), result); + } + if (v.getLeft() == null && v.getRight() == null) { // leaf + result.add(v.getVal()); + } + if (v.getRight() != null) { + allLeafTraversal(v.getRight(), result); + } + } + } + + public static void leftTraversal(BinaryTreeNode v, int low, List result) { + if (v != null) { + if (v.getLeft() == null && v.getRight() == null) { // leaf + result.add(v.getVal()); + } else { + if (low <= v.getVal()) { + leftTraversal(v.getLeft(), low, result); + allLeafTraversal(v.getRight(), result); + } else { + leftTraversal(v.getRight(), low, result); + } + } + } + } + + public static void rightTraversal(BinaryTreeNode v, int high, List result) { + //not exactly symmetrical to right traversal due to v.getval() being max of left subtree + //if v.getval() > high, we dont want to traverse any of its subtrees in right traversal + //but if v.getval < low, we might still want to traverse the right subtree of val + if (v != null) { + if (v.getLeft() == null && v.getRight() == null) { // leaf + result.add(v.getVal()); + } + else { + if (high >= v.getVal()) { + allLeafTraversal(v.getLeft(), result); + rightTraversal(v.getRight(), high, result); + } + } + } + } + + public static Object[] search(int[] inputs, int low, int high) { + BinaryTreeNode tree = OrthogonalRangeSearching.buildTree(inputs, 0, inputs.length - 1); + BinaryTreeNode splitNode = OrthogonalRangeSearching.findSplit(tree, low, high); + ArrayList result = new ArrayList<>(); + if (splitNode != null) { + leftTraversal(splitNode.getLeft(), low, result); + System.out.println(result); + rightTraversal(splitNode.getRight(), high, result); + System.out.println(result); + } + return result.toArray(); + } + +} diff --git a/src/test/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearchingTest.java b/src/test/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearchingTest.java new file mode 100644 index 00000000..59601874 --- /dev/null +++ b/src/test/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearchingTest.java @@ -0,0 +1,41 @@ +package algorithms.orthogonalRangeSearching.oneDim; + +import org.junit.Test; + +import java.util.Arrays; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; + +public class OrthogonalRangeSearchingTest { + + @Test + public void test_OrthogonalRangeSearching() { + + int[] firstInput = new int[] {3, 19, 30, 49, 59, 70, 89, 100}; + Object[] firstExpected = new Object[] {30, 49, 59, 70}; + Object[] firstResult = OrthogonalRangeSearching.search(firstInput, 20, 71); + assertArrayEquals(firstExpected, firstResult); + + int[] secondInput = new int[] {7, 12, 25, 26, 40, 45}; + Object[] secondExpected = new Object[] {12, 25, 26, 40, 45}; + Object[] secondResult = OrthogonalRangeSearching.search(secondInput, 10, 50); + assertArrayEquals(secondExpected, secondResult); + + int[] thirdInput = new int[] {26, 7, 12, 40, 45}; + Object[] thirdExpected = new Object[] {12, 26}; + Object[] thirdResult = OrthogonalRangeSearching.search(thirdInput, 10, 35); + assertArrayEquals(thirdExpected, thirdResult); + + int[] fourthInput = new int[] {-26, -7, -10, -40, -43}; + Object[] fourthExpected = new Object[] {-26, -10, -7}; + Object[] fourthResult = OrthogonalRangeSearching.search(fourthInput, -30, -2); + assertArrayEquals(fourthExpected, fourthResult); + + int[] fifthInput = new int[] {25, 12, 26, 7, 45, 40}; + Object[] fifthExpected = new Object[] {}; + Object[] fifthResult = OrthogonalRangeSearching.search(fifthInput, 0, 5); + assertArrayEquals(fifthExpected, fifthResult); + + } +} diff --git a/src/test/java/algorithms/sorting/insertionSort/InsertionSortTest.java b/src/test/java/algorithms/sorting/insertionSort/InsertionSortTest.java index 1d228960..80e95568 100644 --- a/src/test/java/algorithms/sorting/insertionSort/InsertionSortTest.java +++ b/src/test/java/algorithms/sorting/insertionSort/InsertionSortTest.java @@ -24,7 +24,7 @@ public void test_insertionSort_shouldReturnSortedArray() { int[] fourthArray = new int[] {1}; int[] fourthResult = InsertionSort.sort(Arrays.copyOf(fourthArray, fourthArray.length)); - int[] fifthArray = new int[] {5,1,1,2,0,0}; + int[] fifthArray = new int[] {5, 1, 1, 2, 0, 0}; int[] fifthResult = InsertionSort.sort(Arrays.copyOf(fifthArray, fifthArray.length)); Arrays.sort(firstArray); // get expected result diff --git a/src/test/java/algorithms/sorting/mergeSort/iterative/MergeSortTest.java b/src/test/java/algorithms/sorting/mergeSort/iterative/MergeSortTest.java index 7c981384..b5064a67 100644 --- a/src/test/java/algorithms/sorting/mergeSort/iterative/MergeSortTest.java +++ b/src/test/java/algorithms/sorting/mergeSort/iterative/MergeSortTest.java @@ -28,7 +28,7 @@ public void test_insertionSort_shouldReturnSortedArray() { int[] fourthResult = Arrays.copyOf(fourthArray, fourthArray.length); MergeSort.sort(fourthResult); - int[] fifthArray = new int[] {5,1,1,2,0,0}; + int[] fifthArray = new int[] {5, 1, 1, 2, 0, 0}; int[] fifthResult = Arrays.copyOf(fifthArray, fifthArray.length); MergeSort.sort(fifthResult); diff --git a/src/test/java/algorithms/sorting/mergeSort/recursive/MergeSortTest.java b/src/test/java/algorithms/sorting/mergeSort/recursive/MergeSortTest.java index fe8e5fb1..b3031c16 100644 --- a/src/test/java/algorithms/sorting/mergeSort/recursive/MergeSortTest.java +++ b/src/test/java/algorithms/sorting/mergeSort/recursive/MergeSortTest.java @@ -28,7 +28,7 @@ public void test_insertionSort_shouldReturnSortedArray() { int[] fourthResult = Arrays.copyOf(fourthArray, fourthArray.length); MergeSort.sort(fourthResult); - int[] fifthArray = new int[] {5,1,1,2,0,0}; + int[] fifthArray = new int[] {5, 1, 1, 2, 0, 0}; int[] fifthResult = Arrays.copyOf(fifthArray, fifthArray.length); MergeSort.sort(fifthResult); diff --git a/src/test/java/algorithms/sorting/selectionSort/SelectionSortTest.java b/src/test/java/algorithms/sorting/selectionSort/SelectionSortTest.java index 731e4885..65ffba3a 100644 --- a/src/test/java/algorithms/sorting/selectionSort/SelectionSortTest.java +++ b/src/test/java/algorithms/sorting/selectionSort/SelectionSortTest.java @@ -1,6 +1,6 @@ package algorithms.sorting.selectionSort; -import org.junit.Test; +import org.junit.jupiter.api.Test; import java.util.Arrays; @@ -8,35 +8,33 @@ public class SelectionSortTest { - @Test - public void test_selectionSort_shouldReturnSortedArray() { - int[] firstArray = - new int[] {2, 3, 4, 1, 2, 5, 6, 7, 10, 15, 20, 13, 15, 1, 2, 15, 12, 20, 21, 120, 11, 5, 7, 85, 30}; - int[] firstResult = SelectionSort.sort(Arrays.copyOf(firstArray, firstArray.length)); - - int[] secondArray - = new int[] {9, 1, 2, 8, 7, 3, 4, 6, 5, 5, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - int[] secondResult = SelectionSort.sort(Arrays.copyOf(secondArray, secondArray.length)); - - int[] thirdArray = new int[] {}; - int[] thirdResult = SelectionSort.sort(Arrays.copyOf(thirdArray, thirdArray.length)); - - int[] fourthArray = new int[] {1}; - int[] fourthResult = SelectionSort.sort(Arrays.copyOf(fourthArray, fourthArray.length)); - - int[] fifthArray = new int[] {5,1,1,2,0,0}; - int[] fifthResult = SelectionSort.sort(Arrays.copyOf(fifthArray, fifthArray.length)); - - Arrays.sort(firstArray); // get expected result - Arrays.sort(secondArray); // get expected result - Arrays.sort(thirdArray); // get expected result - Arrays.sort(fourthArray); // get expected result - Arrays.sort(fifthArray); // get expected result - - assertArrayEquals(firstResult, firstArray); - assertArrayEquals(secondResult, secondArray); - assertArrayEquals(thirdResult, thirdArray); - assertArrayEquals(fourthResult, fourthArray); - assertArrayEquals(fifthResult, fifthArray); - } + @Test + public void test_selectionSort_shouldReturnSortedArray() { + final int[] firstArray = new int[] {2, 3, 4, 1, 2, 5, 6, 7, 10, 15, 20, 13, 15, 1, 2, 15, 12, 20, 21, 120, 11, 5, 7, 85, 30}; + final int[] firstResult = SelectionSort.sort(Arrays.copyOf(firstArray, firstArray.length)); + + final int[] secondArray = new int[] {9, 1, 2, 8, 7, 3, 4, 6, 5, 5, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + final int[] secondResult = SelectionSort.sort(Arrays.copyOf(secondArray, secondArray.length)); + + final int[] thirdArray = new int[] {}; + final int[] thirdResult = SelectionSort.sort(Arrays.copyOf(thirdArray, thirdArray.length)); + + final int[] fourthArray = new int[] {1}; + final int[] fourthResult = SelectionSort.sort(Arrays.copyOf(fourthArray, fourthArray.length)); + + final int[] fifthArray = new int[] {5, 1, 1, 2, 0, 0}; + final int[] fifthResult = SelectionSort.sort(Arrays.copyOf(fifthArray, fifthArray.length)); + + Arrays.sort(firstArray); // get expected result + Arrays.sort(secondArray); // get expected result + Arrays.sort(thirdArray); // get expected result + Arrays.sort(fourthArray); // get expected result + Arrays.sort(fifthArray); // get expected result + + assertArrayEquals(firstResult, firstArray); + assertArrayEquals(secondResult, secondArray); + assertArrayEquals(thirdResult, thirdArray); + assertArrayEquals(fourthResult, fourthArray); + assertArrayEquals(fifthResult, fifthArray); + } } From 98003fad18a0014e2cb69c4357c6b3c1bb61053e Mon Sep 17 00:00:00 2001 From: kaitinghh <114789615+kaitinghh@users.noreply.github.com> Date: Sun, 1 Oct 2023 01:56:16 +0800 Subject: [PATCH 02/51] added 1D range tree dynamic updating --- build.gradle | 1 - .../RangeTreeNode.java | 44 ++++ .../oneDim/OrthogonalRangeSearching.java | 245 ++++++++++++++++-- .../oneDim/OrthogonalRangeSearchingTest.java | 85 +++--- .../sorting/bubbleSort/BubbleSortTest.java | 55 ++-- .../insertionSort/InsertionSortTest.java | 66 +++-- .../selectionSort/SelectionSortTest.java | 2 +- 7 files changed, 379 insertions(+), 119 deletions(-) create mode 100644 src/main/java/algorithms/orthogonalRangeSearching/RangeTreeNode.java diff --git a/build.gradle b/build.gradle index c67b79a7..0b5699ff 100644 --- a/build.gradle +++ b/build.gradle @@ -25,7 +25,6 @@ repositories { dependencies { // Use JUnit test framework. testImplementation 'junit:junit:4.13.2' - testImplementation 'org.junit.jupiter:junit-jupiter:5.8.1' } java { diff --git a/src/main/java/algorithms/orthogonalRangeSearching/RangeTreeNode.java b/src/main/java/algorithms/orthogonalRangeSearching/RangeTreeNode.java new file mode 100644 index 00000000..8dd33896 --- /dev/null +++ b/src/main/java/algorithms/orthogonalRangeSearching/RangeTreeNode.java @@ -0,0 +1,44 @@ +package algorithms.orthogonalRangeSearching; + +public class RangeTreeNode { + int val; + int height; + RangeTreeNode left = null; + RangeTreeNode right = null; + RangeTreeNode parent = null; + + public RangeTreeNode(int val) { + this.val = val; + } + public RangeTreeNode(int val, RangeTreeNode left, RangeTreeNode right) { + this.val = val; + this.left = left; + this.right = right; + } + + public int getVal() { return this.val; } + public int getHeight() { return this.height; } + public RangeTreeNode getLeft() { return this.left; } + public RangeTreeNode getRight() { return this.right; } + public RangeTreeNode getParent() { return this.parent; } + + public void setVal(int val) { this.val = val; } + public void setLeft(RangeTreeNode left) { this.left = left; } + public void setRight(RangeTreeNode right) { this.right = right; } + + public void setParent(RangeTreeNode parent) { this.parent = parent; } + public void setHeight(int height) { this.height = height; } + @Override + public boolean equals(Object other) { + if (other == this) { return true; } + if (!(other instanceof RangeTreeNode)) { return false; } + RangeTreeNode node = (RangeTreeNode) other; + return this.val == node.val; + } + + @Override + public int hashCode() { return this.val; } + @Override + public String toString() { return String.valueOf(this.val); } + +} diff --git a/src/main/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearching.java b/src/main/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearching.java index c44cb668..4b93daf1 100644 --- a/src/main/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearching.java +++ b/src/main/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearching.java @@ -1,13 +1,17 @@ package algorithms.orthogonalRangeSearching.oneDim; -import algorithms.graphs.util.BinaryTreeNode; +import algorithms.orthogonalRangeSearching.RangeTreeNode; +import dataStructures.avlTree.Node; + import java.util.Arrays; import java.util.ArrayList; import java.util.List; +import java.util.LinkedList; +import java.util.Queue; public class OrthogonalRangeSearching { - public static BinaryTreeNode buildTree(int[] inputs, int start, int end) { + public static RangeTreeNode buildTree(int[] inputs, int start, int end) { //build range tree from inputs int mid = (end + start) / 2; Arrays.sort(inputs); @@ -15,17 +19,38 @@ public static BinaryTreeNode buildTree(int[] inputs, int start, int end) { if (start > end) { return null; } else if (end - start + 1 > 3) { - return new BinaryTreeNode(inputs[mid], buildTree(inputs, start, mid), buildTree(inputs, mid + 1, end)); + return new RangeTreeNode(inputs[mid], buildTree(inputs, start, mid), buildTree(inputs, mid + 1, end)); } else if (end - start + 1 == 3) { - return new BinaryTreeNode(inputs[mid], buildTree(inputs, start, mid), new BinaryTreeNode(inputs[end])); + return new RangeTreeNode(inputs[mid], buildTree(inputs, start, mid), new RangeTreeNode(inputs[end])); } else if (end - start + 1 == 2) { - return new BinaryTreeNode(inputs[mid], new BinaryTreeNode(inputs[start]), new BinaryTreeNode(inputs[end])); + return new RangeTreeNode(inputs[mid], new RangeTreeNode(inputs[start]), new RangeTreeNode(inputs[end])); + } else { + return new RangeTreeNode(inputs[mid]); + } + } + + public static void configureTree(RangeTreeNode node) { + if (node.getLeft() == null && node.getRight() == null) { + node.setHeight(0); + } else if (node.getLeft() == null) { + configureTree(node.getRight()); + node.setHeight(node.getRight().getHeight() + 1); + node.getRight().setParent(node); + } else if (node.getRight() == null) { + configureTree(node.getLeft()); + node.setHeight(node.getLeft().getHeight() + 1); + node.getLeft().setParent(node); } else { - return new BinaryTreeNode(inputs[mid]); + configureTree(node.getLeft()); + configureTree(node.getRight()); + node.setHeight(Math.max(node.getLeft().getHeight(), node.getRight().getHeight()) + 1); + node.getLeft().setParent(node); + node.getRight().setParent(node); } } - public static BinaryTreeNode findSplit(BinaryTreeNode root, int low, int high) { - BinaryTreeNode v = root; + + public static RangeTreeNode findSplit(RangeTreeNode root, int low, int high) { + RangeTreeNode v = root; while (true) { if (v == null) { @@ -43,7 +68,7 @@ public static BinaryTreeNode findSplit(BinaryTreeNode root, int low, int high) { return v; } - public static void allLeafTraversal(BinaryTreeNode v, List result) { + public static void allLeafTraversal(RangeTreeNode v, List result) { if (v != null) { if (v.getLeft() != null) { allLeafTraversal(v.getLeft(), result); @@ -57,7 +82,7 @@ public static void allLeafTraversal(BinaryTreeNode v, List result) { } } - public static void leftTraversal(BinaryTreeNode v, int low, List result) { + public static void leftTraversal(RangeTreeNode v, int low, List result) { if (v != null) { if (v.getLeft() == null && v.getRight() == null) { // leaf result.add(v.getVal()); @@ -65,41 +90,215 @@ public static void leftTraversal(BinaryTreeNode v, int low, List result if (low <= v.getVal()) { leftTraversal(v.getLeft(), low, result); allLeafTraversal(v.getRight(), result); - } else { + } else { //definitely a qualifying leaf has to exist leftTraversal(v.getRight(), low, result); } } } } - public static void rightTraversal(BinaryTreeNode v, int high, List result) { - //not exactly symmetrical to right traversal due to v.getval() being max of left subtree - //if v.getval() > high, we dont want to traverse any of its subtrees in right traversal - //but if v.getval < low, we might still want to traverse the right subtree of val + public static void rightTraversal(RangeTreeNode v, int high, List result) { if (v != null) { - if (v.getLeft() == null && v.getRight() == null) { // leaf + if (v.getLeft() == null && v.getRight() == null && v.getVal() < high) { // leaf, need extra check result.add(v.getVal()); } else { - if (high >= v.getVal()) { + if (high > v.getVal()) { allLeafTraversal(v.getLeft(), result); rightTraversal(v.getRight(), high, result); - } + } else { //might or might not exist, we are just exploring + rightTraversal(v.getLeft(), high, result); + } } } } - public static Object[] search(int[] inputs, int low, int high) { - BinaryTreeNode tree = OrthogonalRangeSearching.buildTree(inputs, 0, inputs.length - 1); - BinaryTreeNode splitNode = OrthogonalRangeSearching.findSplit(tree, low, high); + public static Object[] search(RangeTreeNode tree, int low, int high) { + RangeTreeNode splitNode = OrthogonalRangeSearching.findSplit(tree, low, high); ArrayList result = new ArrayList<>(); if (splitNode != null) { leftTraversal(splitNode.getLeft(), low, result); - System.out.println(result); rightTraversal(splitNode.getRight(), high, result); - System.out.println(result); } return result.toArray(); } + // Functions from here onwards are designed to support dynamic updates. + + public static RangeTreeNode insert(RangeTreeNode node, int val) { + if (val < node.getVal()) { + if (node.getLeft() != null) { + node.setLeft(insert(node.getLeft(), val)); + } else { + node.setLeft(new RangeTreeNode(val)); + node.getLeft().setParent(node); + node.setRight(new RangeTreeNode(node.getVal())); + node.getRight().setParent(node); + node.setVal(val); + } + } else if (val > node.getVal()) { + if (node.getRight() != null) { + node.setRight(insert(node.getRight(), val)); + } else { + node.setLeft(new RangeTreeNode(node.getVal())); + node.getLeft().setParent(node); + node.setRight(new RangeTreeNode(val)); + node.getRight().setParent(node); + node.setVal(node.getVal()); + + } + } else { + throw new RuntimeException("Duplicate key not supported!"); + } + return rebalance(node); + } + + public static int height(RangeTreeNode node) { + return node == null ? -1 : node.getHeight(); + } + + /** + * Update height of node in range tree during rebalancing. + * @param node node whose height is to be updated + */ + private static void updateHeight(RangeTreeNode node) { + node.setHeight(1 + Math.max(height(node.getLeft()), height(node.getRight()))); + } + + /** + * Get balance factor to check if height-balanced property is violated. + * Note: negative value means tree is right heavy, + * positive value means tree is left heavy, + * 0 means tree is balanced in weight. + * @param node check balance factor of node + * @return int value representing the balance factor + */ + private static int getBalance(RangeTreeNode node) { + return node == null + ? 0 + : height(node.getLeft()) - height(node.getRight()); + } + + /** + * Performs a right rotation on the specified node. + * Note that function should be called only if the + * node has a left child since it will be the + * new root. + * @param n node to perform right rotation on. + * @return the new root after rotation. + */ + private static RangeTreeNode rotateRight(RangeTreeNode n) { + RangeTreeNode newRoot = n.getLeft(); + RangeTreeNode newLeftSub = newRoot.getRight(); + newRoot.setRight(n); + n.setLeft(newLeftSub); + + newRoot.setParent(n.getParent()); + n.setParent(newRoot); + + updateHeight(n); + updateHeight(newRoot); + return newRoot; + } + + /** + * Performs a left rotation on the specified node. + * Note that function should be called only if the + * node has a right child since it will be the + * new root. + * @param n node to perform left rotation on + * @return new root after rotation + */ + private static RangeTreeNode rotateLeft(RangeTreeNode n) { + RangeTreeNode newRoot = n.getRight(); + RangeTreeNode newRightSub = newRoot.getLeft(); + newRoot.setLeft(n); + n.setRight(newRightSub); + + newRoot.setParent(n.getParent()); + n.setParent(newRoot); + + updateHeight(n); + updateHeight(newRoot); + return newRoot; + } + + /** + * Rebalances a node in the tree based on balance factor. + * @param n node to be rebalanced + * @return new root after rebalancing + */ + private static RangeTreeNode rebalance(RangeTreeNode n) { + updateHeight(n); + int balance = getBalance(n); + if (balance < -1) { // right-heavy case + System.out.println("rebalancing"); + if (height(n.getRight().getLeft()) > height(n.getRight().getRight())) { + n.setRight(rotateRight(n.getRight())); + } + n = rotateLeft(n); + } else if (balance > 1) { // left-heavy case + System.out.println("rebalancing"); + if (height(n.getLeft().getRight()) > height(n.getLeft().getLeft())) { + n.setLeft(rotateLeft(n.getLeft())); + } + n = rotateRight(n); + } + return n; + } + + public static RangeTreeNode delete(RangeTreeNode node, int val) { + if (node.getLeft().getLeft() == null && node.getLeft().getRight() == null + && val == node.getLeft().getVal()) { // left node is the leaf node + node.setVal(node.getRight().getVal()); + node.setLeft(null); + node.setRight(null); + } else if (node.getRight().getLeft() == null && node.getRight().getRight() == null + && val == node.getRight().getVal()) { // right node is the leaf node + node.setLeft(null); + node.setRight(null); + } else { + if (val <= node.getVal()) { + if (node.getLeft() != null) { + node.setLeft(delete(node.getLeft(), val)); + } + if (val == node.getVal()) { // duplicate node + node.setVal(getMostRight(node.getLeft()).getVal()); // update the duplicate key + } + } else { + if (node.getRight() != null) { + node.setRight(delete(node.getRight(), val)); + } + } + } + return rebalance(node); + } + + private static RangeTreeNode getMostRight(RangeTreeNode n) { + if (n.getRight() == null) { + return n; + } else { + return getMostRight(n.getRight()); + } + } + + public static void levelOrderTraversal(RangeTreeNode root) { + if (root == null) { + return; + } + + Queue queue = new LinkedList<>(); + queue.add(root); + while (!queue.isEmpty()) { + RangeTreeNode current = queue.poll(); + System.out.print(current.getVal() + " "); + if (current.getLeft() != null) { + queue.add(current.getLeft()); + } + if (current.getRight() != null) { + queue.add(current.getRight()); + } + } + } + } diff --git a/src/test/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearchingTest.java b/src/test/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearchingTest.java index 59601874..7aff2eba 100644 --- a/src/test/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearchingTest.java +++ b/src/test/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearchingTest.java @@ -1,41 +1,62 @@ package algorithms.orthogonalRangeSearching.oneDim; +import algorithms.orthogonalRangeSearching.RangeTreeNode; import org.junit.Test; -import java.util.Arrays; - import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; public class OrthogonalRangeSearchingTest { - - @Test - public void test_OrthogonalRangeSearching() { - - int[] firstInput = new int[] {3, 19, 30, 49, 59, 70, 89, 100}; - Object[] firstExpected = new Object[] {30, 49, 59, 70}; - Object[] firstResult = OrthogonalRangeSearching.search(firstInput, 20, 71); - assertArrayEquals(firstExpected, firstResult); - - int[] secondInput = new int[] {7, 12, 25, 26, 40, 45}; - Object[] secondExpected = new Object[] {12, 25, 26, 40, 45}; - Object[] secondResult = OrthogonalRangeSearching.search(secondInput, 10, 50); - assertArrayEquals(secondExpected, secondResult); - - int[] thirdInput = new int[] {26, 7, 12, 40, 45}; - Object[] thirdExpected = new Object[] {12, 26}; - Object[] thirdResult = OrthogonalRangeSearching.search(thirdInput, 10, 35); - assertArrayEquals(thirdExpected, thirdResult); - - int[] fourthInput = new int[] {-26, -7, -10, -40, -43}; - Object[] fourthExpected = new Object[] {-26, -10, -7}; - Object[] fourthResult = OrthogonalRangeSearching.search(fourthInput, -30, -2); - assertArrayEquals(fourthExpected, fourthResult); - - int[] fifthInput = new int[] {25, 12, 26, 7, 45, 40}; - Object[] fifthExpected = new Object[] {}; - Object[] fifthResult = OrthogonalRangeSearching.search(fifthInput, 0, 5); - assertArrayEquals(fifthExpected, fifthResult); - + @Test + public void test_OrthogonalRangeSearching() { + + int[] firstInput = new int[] {7, 12, 25, 26, 40, 45}; + Object[] firstExpected = new Object[] {12, 25, 26, 40, 45}; + RangeTreeNode firstTree = OrthogonalRangeSearching.buildTree(firstInput, 0, firstInput.length - 1); + Object[] firstResult = OrthogonalRangeSearching.search(firstTree, 10, 50); + assertArrayEquals(firstExpected, firstResult); + + int[] secondInput = new int[] {-26, -7, -10, -40, -43}; + Object[] secondExpected = new Object[] {-26, -10, -7}; + RangeTreeNode secondTree = OrthogonalRangeSearching.buildTree(secondInput, 0, secondInput.length - 1); + Object[] secondResult = OrthogonalRangeSearching.search(secondTree, -30, -2); + assertArrayEquals(secondExpected, secondResult); + + int[] thirdInput = new int[] {26, 7, 12, 40, 45}; + Object[] thirdExpected = new Object[] {12, 26}; + RangeTreeNode thirdTree = OrthogonalRangeSearching.buildTree(thirdInput, 0, thirdInput.length - 1); + Object[] thirdResult = OrthogonalRangeSearching.search(thirdTree, 10, 35); + assertArrayEquals(thirdExpected, thirdResult); + + // for fourth input + // static queries + int[] fourthInput = new int[] {3, 19, 30, 49, 59, 70, 89, 100}; + Object[] fourthExpected = new Object[] {30, 49, 59, 70}; + RangeTreeNode fourthTree = OrthogonalRangeSearching.buildTree(fourthInput, 0, fourthInput.length - 1); + Object[] fourthResult = OrthogonalRangeSearching.search(fourthTree, 20, 71); + assertArrayEquals(fourthExpected, fourthResult); + + Object[] fifthExpected = new Object[] {49, 59, 70, 89, 100}; + Object[] fifthResult = OrthogonalRangeSearching.search(fourthTree, 31, 130); + assertArrayEquals(fifthExpected, fifthResult); + + // dynamic updates then query + + OrthogonalRangeSearching.configureTree(fourthTree); + fourthTree = OrthogonalRangeSearching.insert(fourthTree, 101); + Object[] sixthExpected = new Object[] {49, 59, 70, 89, 100, 101}; + Object[] sixthResult = OrthogonalRangeSearching.search(fourthTree, 31, 130); + assertArrayEquals(sixthExpected, sixthResult); + + fourthTree = OrthogonalRangeSearching.insert(fourthTree, 46); + fourthTree = OrthogonalRangeSearching.insert(fourthTree, 32); + Object[] seventhExpected = new Object[] {30, 32, 46, 49, 59, 70}; + Object[] seventhResult = OrthogonalRangeSearching.search(fourthTree, 20, 71); + assertArrayEquals(seventhExpected, seventhResult); + + fourthTree = OrthogonalRangeSearching.delete(fourthTree, 32); + fourthTree = OrthogonalRangeSearching.delete(fourthTree, 59); + Object[] eighthExpected = new Object[] {30, 46, 49, 70}; + Object[] eighthResult = OrthogonalRangeSearching.search(fourthTree, 20, 72); + assertArrayEquals(eighthExpected, eighthResult); } } diff --git a/src/test/java/algorithms/sorting/bubbleSort/BubbleSortTest.java b/src/test/java/algorithms/sorting/bubbleSort/BubbleSortTest.java index 9c094af9..a4a9a842 100644 --- a/src/test/java/algorithms/sorting/bubbleSort/BubbleSortTest.java +++ b/src/test/java/algorithms/sorting/bubbleSort/BubbleSortTest.java @@ -1,36 +1,35 @@ package algorithms.sorting.bubbleSort; -import org.junit.Test; - import java.util.Arrays; +import org.junit.Test; import static org.junit.Assert.assertArrayEquals; public class BubbleSortTest { - @Test - public void test_bubbleSort_shouldReturnSortedArray() { - int[] firstArray = - new int[] {2, 3, 4, 1, 2, 5, 6, 7, 10, 15, 20, 13, 15, 1, 2, 15, 12, 20, 21, 120, 11, 5, 7, 85, 30}; - int[] firstResult = BubbleSort.sort(Arrays.copyOf(firstArray, firstArray.length)); - - int[] secondArray - = new int[] {9, 1, 2, 8, 7, 3, 4, 6, 5, 5, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - int[] secondResult = BubbleSort.sort(Arrays.copyOf(secondArray, secondArray.length)); - - int[] thirdArray = new int[] {}; - int[] thirdResult = BubbleSort.sort(Arrays.copyOf(thirdArray, thirdArray.length)); - - int[] fourthArray = new int[] {1}; - int[] fourthResult = BubbleSort.sort(Arrays.copyOf(fourthArray, fourthArray.length)); - - Arrays.sort(firstArray); - Arrays.sort(secondArray); - Arrays.sort(thirdArray); - Arrays.sort(fourthArray); - - assertArrayEquals(firstResult, firstArray); - assertArrayEquals(secondResult, secondArray); - assertArrayEquals(thirdResult, thirdArray); - assertArrayEquals(fourthResult, fourthArray); - } + @Test + public void test_bubbleSort_shouldReturnSortedArray() { + int[] firstArray = + new int[] {2, 3, 4, 1, 2, 5, 6, 7, 10, 15, 20, 13, 15, 1, 2, 15, 12, 20, 21, 120, 11, 5, 7, 85, 30}; + int[] firstResult = BubbleSort.sort(Arrays.copyOf(firstArray, firstArray.length)); + + int[] secondArray = + new int[] {9, 1, 2, 8, 7, 3, 4, 6, 5, 5, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + int[] secondResult = BubbleSort.sort(Arrays.copyOf(secondArray, secondArray.length)); + + int[] thirdArray = new int[] {}; + int[] thirdResult = BubbleSort.sort(Arrays.copyOf(thirdArray, thirdArray.length)); + + int[] fourthArray = new int[] {1}; + int[] fourthResult = BubbleSort.sort(Arrays.copyOf(fourthArray, fourthArray.length)); + + Arrays.sort(firstArray); + Arrays.sort(secondArray); + Arrays.sort(thirdArray); + Arrays.sort(fourthArray); + + assertArrayEquals(firstResult, firstArray); + assertArrayEquals(secondResult, secondArray); + assertArrayEquals(thirdResult, thirdArray); + assertArrayEquals(fourthResult, fourthArray); + } } diff --git a/src/test/java/algorithms/sorting/insertionSort/InsertionSortTest.java b/src/test/java/algorithms/sorting/insertionSort/InsertionSortTest.java index 80e95568..18cb1cab 100644 --- a/src/test/java/algorithms/sorting/insertionSort/InsertionSortTest.java +++ b/src/test/java/algorithms/sorting/insertionSort/InsertionSortTest.java @@ -1,42 +1,40 @@ package algorithms.sorting.insertionSort; -import org.junit.Test; - import java.util.Arrays; +import org.junit.Test; import static org.junit.Assert.assertArrayEquals; public class InsertionSortTest { - - @Test - public void test_insertionSort_shouldReturnSortedArray() { - int[] firstArray = - new int[] {2, 3, 4, 1, 2, 5, 6, 7, 10, 15, 20, 13, 15, 1, 2, 15, 12, 20, 21, 120, 11, 5, 7, 85, 30}; - int[] firstResult = InsertionSort.sort(Arrays.copyOf(firstArray, firstArray.length)); - - int[] secondArray - = new int[] {9, 1, 2, 8, 7, 3, 4, 6, 5, 5, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - int[] secondResult = InsertionSort.sort(Arrays.copyOf(secondArray, secondArray.length)); - - int[] thirdArray = new int[] {}; - int[] thirdResult = InsertionSort.sort(Arrays.copyOf(thirdArray, thirdArray.length)); - - int[] fourthArray = new int[] {1}; - int[] fourthResult = InsertionSort.sort(Arrays.copyOf(fourthArray, fourthArray.length)); - - int[] fifthArray = new int[] {5, 1, 1, 2, 0, 0}; - int[] fifthResult = InsertionSort.sort(Arrays.copyOf(fifthArray, fifthArray.length)); - - Arrays.sort(firstArray); // get expected result - Arrays.sort(secondArray); // get expected result - Arrays.sort(thirdArray); // get expected result - Arrays.sort(fourthArray); // get expected result - Arrays.sort(fifthArray); // get expected result - - assertArrayEquals(firstResult, firstArray); - assertArrayEquals(secondResult, secondArray); - assertArrayEquals(thirdResult, thirdArray); - assertArrayEquals(fourthResult, fourthArray); - assertArrayEquals(fifthResult, fifthArray); - } + @Test + public void test_insertionSort_shouldReturnSortedArray() { + int[] firstArray = + new int[] {2, 3, 4, 1, 2, 5, 6, 7, 10, 15, 20, 13, 15, 1, 2, 15, 12, 20, 21, 120, 11, 5, 7, 85, 30}; + int[] firstResult = InsertionSort.sort(Arrays.copyOf(firstArray, firstArray.length)); + + int[] secondArray = + new int[] {9, 1, 2, 8, 7, 3, 4, 6, 5, 5, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + int[] secondResult = InsertionSort.sort(Arrays.copyOf(secondArray, secondArray.length)); + + int[] thirdArray = new int[] {}; + int[] thirdResult = InsertionSort.sort(Arrays.copyOf(thirdArray, thirdArray.length)); + + int[] fourthArray = new int[] {1}; + int[] fourthResult = InsertionSort.sort(Arrays.copyOf(fourthArray, fourthArray.length)); + + int[] fifthArray = new int[] {5, 1, 1, 2, 0, 0}; + int[] fifthResult = InsertionSort.sort(Arrays.copyOf(fifthArray, fifthArray.length)); + + Arrays.sort(firstArray); // get expected result + Arrays.sort(secondArray); // get expected result + Arrays.sort(thirdArray); // get expected result + Arrays.sort(fourthArray); // get expected result + Arrays.sort(fifthArray); // get expected result + + assertArrayEquals(firstResult, firstArray); + assertArrayEquals(secondResult, secondArray); + assertArrayEquals(thirdResult, thirdArray); + assertArrayEquals(fourthResult, fourthArray); + assertArrayEquals(fifthResult, fifthArray); + } } diff --git a/src/test/java/algorithms/sorting/selectionSort/SelectionSortTest.java b/src/test/java/algorithms/sorting/selectionSort/SelectionSortTest.java index 65ffba3a..ef972bed 100644 --- a/src/test/java/algorithms/sorting/selectionSort/SelectionSortTest.java +++ b/src/test/java/algorithms/sorting/selectionSort/SelectionSortTest.java @@ -1,6 +1,6 @@ package algorithms.sorting.selectionSort; -import org.junit.jupiter.api.Test; +import org.junit.Test; import java.util.Arrays; From dcf0343bb5e02c4f5cdb3220d8912fc1f0efa94b Mon Sep 17 00:00:00 2001 From: kaitinghh <114789615+kaitinghh@users.noreply.github.com> Date: Tue, 3 Oct 2023 21:48:33 +0800 Subject: [PATCH 03/51] added documentation --- .../oneDim/OrthogonalRangeSearching.java | 140 ++++++++++++++---- 1 file changed, 108 insertions(+), 32 deletions(-) diff --git a/src/main/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearching.java b/src/main/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearching.java index 4b93daf1..6ca271b6 100644 --- a/src/main/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearching.java +++ b/src/main/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearching.java @@ -1,7 +1,6 @@ package algorithms.orthogonalRangeSearching.oneDim; import algorithms.orthogonalRangeSearching.RangeTreeNode; -import dataStructures.avlTree.Node; import java.util.Arrays; import java.util.ArrayList; @@ -11,8 +10,16 @@ public class OrthogonalRangeSearching { + /** + * Builds a Range Tree from an array of integers. + * + * @param inputs The array of integers. + * @param start The starting index of the input array. + * @param end The ending index of the input array. + * @return The root node of the constructed Range Tree. + */ public static RangeTreeNode buildTree(int[] inputs, int start, int end) { - //build range tree from inputs + int mid = (end + start) / 2; Arrays.sort(inputs); @@ -29,26 +36,14 @@ public static RangeTreeNode buildTree(int[] inputs, int start, int end) { } } - public static void configureTree(RangeTreeNode node) { - if (node.getLeft() == null && node.getRight() == null) { - node.setHeight(0); - } else if (node.getLeft() == null) { - configureTree(node.getRight()); - node.setHeight(node.getRight().getHeight() + 1); - node.getRight().setParent(node); - } else if (node.getRight() == null) { - configureTree(node.getLeft()); - node.setHeight(node.getLeft().getHeight() + 1); - node.getLeft().setParent(node); - } else { - configureTree(node.getLeft()); - configureTree(node.getRight()); - node.setHeight(Math.max(node.getLeft().getHeight(), node.getRight().getHeight()) + 1); - node.getLeft().setParent(node); - node.getRight().setParent(node); - } - } - + /** + * Finds the split node in the Range Tree based on a given range. + * + * @param root The root node of the Range Tree. + * @param low The lower bound of the range. + * @param high The upper bound of the range. + * @return The split node in the Range Tree. + */ public static RangeTreeNode findSplit(RangeTreeNode root, int low, int high) { RangeTreeNode v = root; @@ -68,6 +63,12 @@ public static RangeTreeNode findSplit(RangeTreeNode root, int low, int high) { return v; } + /** + * Performs a recursive traversal of the Range Tree and adds leaf node values to the result list. + * + * @param v The current node being processed during traversal. + * @param result The list to store the values of leaf nodes encountered during traversal. + */ public static void allLeafTraversal(RangeTreeNode v, List result) { if (v != null) { if (v.getLeft() != null) { @@ -82,6 +83,13 @@ public static void allLeafTraversal(RangeTreeNode v, List result) { } } + /** + * Performs a left traversal of the Range Tree to find nodes within a specified range. + * + * @param v The current node being processed. + * @param low The lower bound of the range. + * @param result A list to store the results of the traversal. + */ public static void leftTraversal(RangeTreeNode v, int low, List result) { if (v != null) { if (v.getLeft() == null && v.getRight() == null) { // leaf @@ -90,13 +98,20 @@ public static void leftTraversal(RangeTreeNode v, int low, List result) if (low <= v.getVal()) { leftTraversal(v.getLeft(), low, result); allLeafTraversal(v.getRight(), result); - } else { //definitely a qualifying leaf has to exist + } else { // definitely a qualifying leaf has to exist leftTraversal(v.getRight(), low, result); } } } } + /** + * Performs a right traversal of the Range Tree to find nodes within a specified range. + * + * @param v The current node being processed. + * @param high The upper bound of the range. + * @param result A list to store the results of the traversal. + */ public static void rightTraversal(RangeTreeNode v, int high, List result) { if (v != null) { if (v.getLeft() == null && v.getRight() == null && v.getVal() < high) { // leaf, need extra check @@ -106,13 +121,21 @@ public static void rightTraversal(RangeTreeNode v, int high, List resul if (high > v.getVal()) { allLeafTraversal(v.getLeft(), result); rightTraversal(v.getRight(), high, result); - } else { //might or might not exist, we are just exploring + } else { // a qualifying leaf might or might not exist, we are just exploring rightTraversal(v.getLeft(), high, result); } } } } + /** + * Searches for elements within a specified range in the Range Tree. + * + * @param tree The root node of the Range Tree. + * @param low The lower bound of the range. + * @param high The upper bound of the range. + * @return An array of elements within the specified range. + */ public static Object[] search(RangeTreeNode tree, int low, int high) { RangeTreeNode splitNode = OrthogonalRangeSearching.findSplit(tree, low, high); ArrayList result = new ArrayList<>(); @@ -125,6 +148,39 @@ public static Object[] search(RangeTreeNode tree, int low, int high) { // Functions from here onwards are designed to support dynamic updates. + /** + * Configures the height and parent nodes for the nodes in the Range Tree. + * Note that this is only needed if we want to support dynamic updating of the range tree. + * + * @param node The root node of the Range Tree. + */ + public static void configureTree(RangeTreeNode node) { + if (node.getLeft() == null && node.getRight() == null) { + node.setHeight(0); + } else if (node.getLeft() == null) { + configureTree(node.getRight()); + node.setHeight(node.getRight().getHeight() + 1); + node.getRight().setParent(node); + } else if (node.getRight() == null) { + configureTree(node.getLeft()); + node.setHeight(node.getLeft().getHeight() + 1); + node.getLeft().setParent(node); + } else { + configureTree(node.getLeft()); + configureTree(node.getRight()); + node.setHeight(Math.max(node.getLeft().getHeight(), node.getRight().getHeight()) + 1); + node.getLeft().setParent(node); + node.getRight().setParent(node); + } + } + + /** + * Inserts a new element into the Range Tree while maintaining balance. + * + * @param node The root node of the Range Tree. + * @param val The value to be inserted. + * @return The root node of the updated Range Tree. + */ public static RangeTreeNode insert(RangeTreeNode node, int val) { if (val < node.getVal()) { if (node.getLeft() != null) { @@ -153,6 +209,12 @@ public static RangeTreeNode insert(RangeTreeNode node, int val) { return rebalance(node); } + /** + * Calculates and returns the height of the given Range Tree node. + * + * @param node The Range Tree node for which to calculate the height. + * @return The height of the node, or -1 if the node is null. + */ public static int height(RangeTreeNode node) { return node == null ? -1 : node.getHeight(); } @@ -181,9 +243,7 @@ private static int getBalance(RangeTreeNode node) { /** * Performs a right rotation on the specified node. - * Note that function should be called only if the - * node has a left child since it will be the - * new root. + * Note that function should be called only if the node has a left child since it will be the new root. * @param n node to perform right rotation on. * @return the new root after rotation. */ @@ -203,9 +263,7 @@ private static RangeTreeNode rotateRight(RangeTreeNode n) { /** * Performs a left rotation on the specified node. - * Note that function should be called only if the - * node has a right child since it will be the - * new root. + * Note that function should be called only if the node has a right child since it will be the new root. * @param n node to perform left rotation on * @return new root after rotation */ @@ -232,13 +290,11 @@ private static RangeTreeNode rebalance(RangeTreeNode n) { updateHeight(n); int balance = getBalance(n); if (balance < -1) { // right-heavy case - System.out.println("rebalancing"); if (height(n.getRight().getLeft()) > height(n.getRight().getRight())) { n.setRight(rotateRight(n.getRight())); } n = rotateLeft(n); } else if (balance > 1) { // left-heavy case - System.out.println("rebalancing"); if (height(n.getLeft().getRight()) > height(n.getLeft().getLeft())) { n.setLeft(rotateLeft(n.getLeft())); } @@ -247,6 +303,13 @@ private static RangeTreeNode rebalance(RangeTreeNode n) { return n; } + /** + * Deletes an element from the Range Tree while maintaining balance. + * + * @param node The root node of the Range Tree. + * @param val The value to be deleted. + * @return The root node of the updated Range Tree. + */ public static RangeTreeNode delete(RangeTreeNode node, int val) { if (node.getLeft().getLeft() == null && node.getLeft().getRight() == null && val == node.getLeft().getVal()) { // left node is the leaf node @@ -274,6 +337,12 @@ public static RangeTreeNode delete(RangeTreeNode node, int val) { return rebalance(node); } + /** + * Finds and returns the rightmost node in the Range Tree rooted at the given node. + * + * @param n The root node of a subtree to search in. + * @return The rightmost node in the subtree, or null if the input node is null. + */ private static RangeTreeNode getMostRight(RangeTreeNode n) { if (n.getRight() == null) { return n; @@ -282,6 +351,13 @@ private static RangeTreeNode getMostRight(RangeTreeNode n) { } } + /** + * Performs a level order traversal of the Range Tree and prints the elements. + * This is not a necessary function for orthogonal range searching, but merely a utility function for debugging + * and visualisation purposes. + * + * @param root The root node of the Range Tree. + */ public static void levelOrderTraversal(RangeTreeNode root) { if (root == null) { return; From a9c021b8328f50f8e1d2c5600d3c79558edb7a44 Mon Sep 17 00:00:00 2001 From: kaitinghh <114789615+kaitinghh@users.noreply.github.com> Date: Tue, 17 Oct 2023 21:57:36 +0800 Subject: [PATCH 04/51] added 2d ors --- .../RangeTreeNode.java | 90 ++- .../oneDim/OrthogonalRangeSearching.java | 670 +++++++++--------- .../orthogonalRangeSearching/oneDim/README.md | 13 + .../twoDim/OrthogonalRangeSearching.java | 314 ++++++++ .../oneDim/OrthogonalRangeSearchingTest.java | 22 +- .../twoDim/OrthogonalRangeSearchingTest.java | 47 ++ 6 files changed, 792 insertions(+), 364 deletions(-) create mode 100644 src/main/java/algorithms/orthogonalRangeSearching/oneDim/README.md create mode 100644 src/main/java/algorithms/orthogonalRangeSearching/twoDim/OrthogonalRangeSearching.java create mode 100644 src/test/java/algorithms/orthogonalRangeSearching/twoDim/OrthogonalRangeSearchingTest.java diff --git a/src/main/java/algorithms/orthogonalRangeSearching/RangeTreeNode.java b/src/main/java/algorithms/orthogonalRangeSearching/RangeTreeNode.java index 8dd33896..a55b9b5f 100644 --- a/src/main/java/algorithms/orthogonalRangeSearching/RangeTreeNode.java +++ b/src/main/java/algorithms/orthogonalRangeSearching/RangeTreeNode.java @@ -1,44 +1,86 @@ package algorithms.orthogonalRangeSearching; -public class RangeTreeNode { - int val; +public class RangeTreeNode { + T val; int height; - RangeTreeNode left = null; - RangeTreeNode right = null; - RangeTreeNode parent = null; + RangeTreeNode left = null; + RangeTreeNode right = null; + RangeTreeNode parent = null; + RangeTreeNode yTree = null; - public RangeTreeNode(int val) { + public RangeTreeNode(T val) { this.val = val; } - public RangeTreeNode(int val, RangeTreeNode left, RangeTreeNode right) { + + public RangeTreeNode(T val, RangeTreeNode left, RangeTreeNode right) { + this.val = val; + this.left = left; + this.right = right; + } + + public T getVal() { + return this.val; + } + + public int getHeight() { + return this.height; + } + + public RangeTreeNode getLeft() { + return this.left; + } + + public RangeTreeNode getRight() { + return this.right; + } + + public RangeTreeNode getParent() { + return this.parent; + } + + public RangeTreeNode getYTree() { + return this.yTree; + } + + public void setVal(T val) { this.val = val; + } + + public void setLeft(RangeTreeNode left) { this.left = left; + } + + public void setRight(RangeTreeNode right) { this.right = right; } - public int getVal() { return this.val; } - public int getHeight() { return this.height; } - public RangeTreeNode getLeft() { return this.left; } - public RangeTreeNode getRight() { return this.right; } - public RangeTreeNode getParent() { return this.parent; } + public void setParent(RangeTreeNode parent) { + this.parent = parent; + } - public void setVal(int val) { this.val = val; } - public void setLeft(RangeTreeNode left) { this.left = left; } - public void setRight(RangeTreeNode right) { this.right = right; } + public void setHeight(int height) { + this.height = height; + } + + public void setYTree(RangeTreeNode yTree) { + this.yTree = yTree; + } - public void setParent(RangeTreeNode parent) { this.parent = parent; } - public void setHeight(int height) { this.height = height; } @Override public boolean equals(Object other) { - if (other == this) { return true; } - if (!(other instanceof RangeTreeNode)) { return false; } - RangeTreeNode node = (RangeTreeNode) other; - return this.val == node.val; + if (other == this) { + return true; + } + if (!(other instanceof RangeTreeNode)) { + return false; + } + RangeTreeNode node = (RangeTreeNode) other; + return this.val == node.val; } @Override - public int hashCode() { return this.val; } - @Override - public String toString() { return String.valueOf(this.val); } + public String toString() { + return String.valueOf(this.val); + } } diff --git a/src/main/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearching.java b/src/main/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearching.java index 6ca271b6..b88e0d7f 100644 --- a/src/main/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearching.java +++ b/src/main/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearching.java @@ -1,380 +1,388 @@ package algorithms.orthogonalRangeSearching.oneDim; import algorithms.orthogonalRangeSearching.RangeTreeNode; - -import java.util.Arrays; import java.util.ArrayList; -import java.util.List; +import java.util.Arrays; import java.util.LinkedList; +import java.util.List; import java.util.Queue; public class OrthogonalRangeSearching { + /** + * Builds a Range Tree from an array of integers. + * + * @param inputs The array of integers. + * @param start The starting index of the input array. + * @param end The ending index of the input array. + * @return The root node of the constructed Range Tree. + */ + public static RangeTreeNode buildTree(int[] inputs, int start, int end) { + int mid = (end + start) / 2; + Arrays.sort(inputs); - /** - * Builds a Range Tree from an array of integers. - * - * @param inputs The array of integers. - * @param start The starting index of the input array. - * @param end The ending index of the input array. - * @return The root node of the constructed Range Tree. - */ - public static RangeTreeNode buildTree(int[] inputs, int start, int end) { - - int mid = (end + start) / 2; - Arrays.sort(inputs); - - if (start > end) { - return null; - } else if (end - start + 1 > 3) { - return new RangeTreeNode(inputs[mid], buildTree(inputs, start, mid), buildTree(inputs, mid + 1, end)); - } else if (end - start + 1 == 3) { - return new RangeTreeNode(inputs[mid], buildTree(inputs, start, mid), new RangeTreeNode(inputs[end])); - } else if (end - start + 1 == 2) { - return new RangeTreeNode(inputs[mid], new RangeTreeNode(inputs[start]), new RangeTreeNode(inputs[end])); - } else { - return new RangeTreeNode(inputs[mid]); - } + if (start > end) { + return null; + } else if (end - start + 1 > 3) { + return new RangeTreeNode<>(inputs[mid], buildTree(inputs, start, mid), + buildTree(inputs, mid + 1, end)); + } else if (end - start + 1 == 3) { + return new RangeTreeNode<>(inputs[mid], buildTree(inputs, start, mid), + buildTree(inputs, end, end)); + } else if (end - start + 1 == 2) { + return new RangeTreeNode<>(inputs[mid], buildTree(inputs, start, start), + buildTree(inputs, end, end)); + } else { + return new RangeTreeNode<>(inputs[mid]); } + } - /** - * Finds the split node in the Range Tree based on a given range. - * - * @param root The root node of the Range Tree. - * @param low The lower bound of the range. - * @param high The upper bound of the range. - * @return The split node in the Range Tree. - */ - public static RangeTreeNode findSplit(RangeTreeNode root, int low, int high) { - RangeTreeNode v = root; + /** + * Finds the split node in the Range Tree based on a given range. + * + * @param root The root node of the Range Tree. + * @param low The lower bound of the range. + * @param high The upper bound of the range. + * @return The split node in the Range Tree. + */ + public static RangeTreeNode findSplit(RangeTreeNode root, int low, int high) { + RangeTreeNode v = root; - while (true) { - if (v == null) { - return null; - } else { - if (high <= v.getVal()) { - v = v.getLeft(); - } else if (low > v.getVal()) { - v = v.getRight(); - } else { - break; - } - } + while (true) { + if (v == null) { + return null; + } else { + if (high <= v.getVal()) { + if (v.getLeft() == null && v.getRight() == null) { // reached the leaf + break; + } + v = v.getLeft(); + } else if (low > v.getVal()) { + v = v.getRight(); + } else { + break; } - return v; + } } + return v; + } - /** - * Performs a recursive traversal of the Range Tree and adds leaf node values to the result list. - * - * @param v The current node being processed during traversal. - * @param result The list to store the values of leaf nodes encountered during traversal. - */ - public static void allLeafTraversal(RangeTreeNode v, List result) { - if (v != null) { - if (v.getLeft() != null) { - allLeafTraversal(v.getLeft(), result); - } - if (v.getLeft() == null && v.getRight() == null) { // leaf - result.add(v.getVal()); - } - if (v.getRight() != null) { - allLeafTraversal(v.getRight(), result); - } - } + /** + * Performs a recursive traversal of the Range Tree and adds leaf node values to the result list. + * + * @param v The current node being processed during traversal. + * @param result The list to store the values of leaf nodes encountered during traversal. + */ + public static void allLeafTraversal(RangeTreeNode v, List result) { + if (v != null) { + if (v.getLeft() != null) { + allLeafTraversal(v.getLeft(), result); + } + if (v.getLeft() == null && v.getRight() == null) { // leaf + result.add(v.getVal()); + } + if (v.getRight() != null) { + allLeafTraversal(v.getRight(), result); + } } + } - /** - * Performs a left traversal of the Range Tree to find nodes within a specified range. - * - * @param v The current node being processed. - * @param low The lower bound of the range. - * @param result A list to store the results of the traversal. - */ - public static void leftTraversal(RangeTreeNode v, int low, List result) { - if (v != null) { - if (v.getLeft() == null && v.getRight() == null) { // leaf - result.add(v.getVal()); - } else { - if (low <= v.getVal()) { - leftTraversal(v.getLeft(), low, result); - allLeafTraversal(v.getRight(), result); - } else { // definitely a qualifying leaf has to exist - leftTraversal(v.getRight(), low, result); - } - } + /** + * Performs a left traversal of the Range Tree to find nodes within a specified range. + * + * @param v The current node being processed. + * @param low The lower bound of the range. + * @param result A list to store the results of the traversal. + */ + public static void leftTraversal(RangeTreeNode v, int low, List result) { + if (v != null) { + if (v.getLeft() == null && v.getRight() == null) { // leaf + result.add(v.getVal()); + } else { + if (low <= v.getVal()) { + leftTraversal(v.getLeft(), low, result); + allLeafTraversal(v.getRight(), result); + } else { // definitely a qualifying leaf has to exist + leftTraversal(v.getRight(), low, result); } + } } + } - /** - * Performs a right traversal of the Range Tree to find nodes within a specified range. - * - * @param v The current node being processed. - * @param high The upper bound of the range. - * @param result A list to store the results of the traversal. - */ - public static void rightTraversal(RangeTreeNode v, int high, List result) { - if (v != null) { - if (v.getLeft() == null && v.getRight() == null && v.getVal() < high) { // leaf, need extra check - result.add(v.getVal()); - } - else { - if (high > v.getVal()) { - allLeafTraversal(v.getLeft(), result); - rightTraversal(v.getRight(), high, result); - } else { // a qualifying leaf might or might not exist, we are just exploring - rightTraversal(v.getLeft(), high, result); - } - } + /** + * Performs a right traversal of the Range Tree to find nodes within a specified range. + * + * @param v The current node being processed. + * @param high The upper bound of the range. + * @param result A list to store the results of the traversal. + */ + public static void rightTraversal(RangeTreeNode v, int high, List result) { + if (v != null) { + if (v.getLeft() == null && v.getRight() == null && v.getVal() <= high) { // leaf, need extra check + result.add(v.getVal()); + } else { + if (high > v.getVal()) { + allLeafTraversal(v.getLeft(), result); + rightTraversal(v.getRight(), high, result); + } else { // a qualifying leaf might or might not exist, we are just exploring + rightTraversal(v.getLeft(), high, result); } + } } + } - /** - * Searches for elements within a specified range in the Range Tree. - * - * @param tree The root node of the Range Tree. - * @param low The lower bound of the range. - * @param high The upper bound of the range. - * @return An array of elements within the specified range. - */ - public static Object[] search(RangeTreeNode tree, int low, int high) { - RangeTreeNode splitNode = OrthogonalRangeSearching.findSplit(tree, low, high); - ArrayList result = new ArrayList<>(); - if (splitNode != null) { - leftTraversal(splitNode.getLeft(), low, result); - rightTraversal(splitNode.getRight(), high, result); - } - return result.toArray(); + /** + * Searches for elements within a specified range in the Range Tree. + * + * @param tree The root node of the Range Tree. + * @param low The lower bound of the range. + * @param high The upper bound of the range. + * @return An array of elements within the specified range. + */ + public static Object[] search(RangeTreeNode tree, int low, int high) { + RangeTreeNode splitNode = OrthogonalRangeSearching.findSplit(tree, low, high); + ArrayList result = new ArrayList<>(); + if (splitNode != null) { + if (splitNode.getLeft() == null && splitNode.getRight() == null + && splitNode.getVal() >= low && splitNode.getVal() <= high) { // if split node is leaf + result.add(splitNode.getVal()); + } + leftTraversal(splitNode.getLeft(), low, result); + rightTraversal(splitNode.getRight(), high, result); } + return result.toArray(); + } - // Functions from here onwards are designed to support dynamic updates. + // Functions from here onwards are designed to support dynamic updates. - /** - * Configures the height and parent nodes for the nodes in the Range Tree. - * Note that this is only needed if we want to support dynamic updating of the range tree. - * - * @param node The root node of the Range Tree. - */ - public static void configureTree(RangeTreeNode node) { - if (node.getLeft() == null && node.getRight() == null) { - node.setHeight(0); - } else if (node.getLeft() == null) { - configureTree(node.getRight()); - node.setHeight(node.getRight().getHeight() + 1); - node.getRight().setParent(node); - } else if (node.getRight() == null) { - configureTree(node.getLeft()); - node.setHeight(node.getLeft().getHeight() + 1); - node.getLeft().setParent(node); - } else { - configureTree(node.getLeft()); - configureTree(node.getRight()); - node.setHeight(Math.max(node.getLeft().getHeight(), node.getRight().getHeight()) + 1); - node.getLeft().setParent(node); - node.getRight().setParent(node); - } + /** + * Configures the height and parent nodes for the nodes in the Range Tree. + * Note that this is only needed if we want to support dynamic updating of the range tree. + * + * @param node The root node of the Range Tree. + */ + public static void configureTree(RangeTreeNode node) { + if (node.getLeft() == null && node.getRight() == null) { + node.setHeight(0); + } else if (node.getLeft() == null) { + configureTree(node.getRight()); + node.setHeight(node.getRight().getHeight() + 1); + node.getRight().setParent(node); + } else if (node.getRight() == null) { + configureTree(node.getLeft()); + node.setHeight(node.getLeft().getHeight() + 1); + node.getLeft().setParent(node); + } else { + configureTree(node.getLeft()); + configureTree(node.getRight()); + node.setHeight(Math.max(node.getLeft().getHeight(), node.getRight().getHeight()) + 1); + node.getLeft().setParent(node); + node.getRight().setParent(node); } + } - /** - * Inserts a new element into the Range Tree while maintaining balance. - * - * @param node The root node of the Range Tree. - * @param val The value to be inserted. - * @return The root node of the updated Range Tree. - */ - public static RangeTreeNode insert(RangeTreeNode node, int val) { - if (val < node.getVal()) { - if (node.getLeft() != null) { - node.setLeft(insert(node.getLeft(), val)); - } else { - node.setLeft(new RangeTreeNode(val)); - node.getLeft().setParent(node); - node.setRight(new RangeTreeNode(node.getVal())); - node.getRight().setParent(node); - node.setVal(val); - } - } else if (val > node.getVal()) { - if (node.getRight() != null) { - node.setRight(insert(node.getRight(), val)); - } else { - node.setLeft(new RangeTreeNode(node.getVal())); - node.getLeft().setParent(node); - node.setRight(new RangeTreeNode(val)); - node.getRight().setParent(node); - node.setVal(node.getVal()); - - } - } else { - throw new RuntimeException("Duplicate key not supported!"); - } - return rebalance(node); + /** + * Inserts a new element into the Range Tree while maintaining balance. + * + * @param node The root node of the Range Tree. + * @param val The value to be inserted. + * @return The root node of the updated Range Tree. + */ + public static RangeTreeNode insert(RangeTreeNode node, int val) { + if (val < node.getVal()) { + if (node.getLeft() != null) { + node.setLeft(insert(node.getLeft(), val)); + } else { + node.setLeft(new RangeTreeNode(val)); + node.getLeft().setParent(node); + node.setRight(new RangeTreeNode(node.getVal())); + node.getRight().setParent(node); + node.setVal(val); + } + } else if (val > node.getVal()) { + if (node.getRight() != null) { + node.setRight(insert(node.getRight(), val)); + } else { + node.setLeft(new RangeTreeNode(node.getVal())); + node.getLeft().setParent(node); + node.setRight(new RangeTreeNode(val)); + node.getRight().setParent(node); + node.setVal(node.getVal()); + } + } else { + throw new RuntimeException("Duplicate key not supported!"); } + return rebalance(node); + } - /** - * Calculates and returns the height of the given Range Tree node. - * - * @param node The Range Tree node for which to calculate the height. - * @return The height of the node, or -1 if the node is null. - */ - public static int height(RangeTreeNode node) { - return node == null ? -1 : node.getHeight(); - } + /** + * Calculates and returns the height of the given Range Tree node. + * + * @param node The Range Tree node for which to calculate the height. + * @return The height of the node, or -1 if the node is null. + */ + private static int height(RangeTreeNode node) { + return node == null + ? -1 + : node.getHeight(); + } - /** - * Update height of node in range tree during rebalancing. - * @param node node whose height is to be updated - */ - private static void updateHeight(RangeTreeNode node) { - node.setHeight(1 + Math.max(height(node.getLeft()), height(node.getRight()))); - } + /** + * Update height of node in range tree during rebalancing. + * @param node node whose height is to be updated + */ + private static void updateHeight(RangeTreeNode node) { + node.setHeight(1 + Math.max(height(node.getLeft()), height(node.getRight()))); + } - /** - * Get balance factor to check if height-balanced property is violated. - * Note: negative value means tree is right heavy, - * positive value means tree is left heavy, - * 0 means tree is balanced in weight. - * @param node check balance factor of node - * @return int value representing the balance factor - */ - private static int getBalance(RangeTreeNode node) { - return node == null - ? 0 - : height(node.getLeft()) - height(node.getRight()); - } + /** + * Get balance factor to check if height-balanced property is violated. + * Note: negative value means tree is right heavy, + * positive value means tree is left heavy, + * 0 means tree is balanced in weight. + * @param node check balance factor of node + * @return int value representing the balance factor + */ + private static int getBalance(RangeTreeNode node) { + return node == null + ? 0 + : height(node.getLeft()) - height(node.getRight()); + } - /** - * Performs a right rotation on the specified node. - * Note that function should be called only if the node has a left child since it will be the new root. - * @param n node to perform right rotation on. - * @return the new root after rotation. - */ - private static RangeTreeNode rotateRight(RangeTreeNode n) { - RangeTreeNode newRoot = n.getLeft(); - RangeTreeNode newLeftSub = newRoot.getRight(); - newRoot.setRight(n); - n.setLeft(newLeftSub); + /** + * Performs a right rotation on the specified node. + * Note that function should be called only if the node has a left child since it will be the new root. + * @param n node to perform right rotation on. + * @return the new root after rotation. + */ + private static RangeTreeNode rotateRight(RangeTreeNode n) { + RangeTreeNode newRoot = n.getLeft(); + RangeTreeNode newLeftSub = newRoot.getRight(); + newRoot.setRight(n); + n.setLeft(newLeftSub); - newRoot.setParent(n.getParent()); - n.setParent(newRoot); + newRoot.setParent(n.getParent()); + n.setParent(newRoot); - updateHeight(n); - updateHeight(newRoot); - return newRoot; - } + updateHeight(n); + updateHeight(newRoot); + return newRoot; + } - /** - * Performs a left rotation on the specified node. - * Note that function should be called only if the node has a right child since it will be the new root. - * @param n node to perform left rotation on - * @return new root after rotation - */ - private static RangeTreeNode rotateLeft(RangeTreeNode n) { - RangeTreeNode newRoot = n.getRight(); - RangeTreeNode newRightSub = newRoot.getLeft(); - newRoot.setLeft(n); - n.setRight(newRightSub); + /** + * Performs a left rotation on the specified node. + * Note that function should be called only if the node has a right child since it will be the new root. + * + * @param n node to perform left rotation on + * @return new root after rotation + */ + private static RangeTreeNode rotateLeft(RangeTreeNode n) { + RangeTreeNode newRoot = n.getRight(); + RangeTreeNode newRightSub = newRoot.getLeft(); + newRoot.setLeft(n); + n.setRight(newRightSub); - newRoot.setParent(n.getParent()); - n.setParent(newRoot); + newRoot.setParent(n.getParent()); + n.setParent(newRoot); - updateHeight(n); - updateHeight(newRoot); - return newRoot; - } + updateHeight(n); + updateHeight(newRoot); + return newRoot; + } - /** - * Rebalances a node in the tree based on balance factor. - * @param n node to be rebalanced - * @return new root after rebalancing - */ - private static RangeTreeNode rebalance(RangeTreeNode n) { - updateHeight(n); - int balance = getBalance(n); - if (balance < -1) { // right-heavy case - if (height(n.getRight().getLeft()) > height(n.getRight().getRight())) { - n.setRight(rotateRight(n.getRight())); - } - n = rotateLeft(n); - } else if (balance > 1) { // left-heavy case - if (height(n.getLeft().getRight()) > height(n.getLeft().getLeft())) { - n.setLeft(rotateLeft(n.getLeft())); - } - n = rotateRight(n); - } - return n; + /** + * Rebalances a node in the tree based on balance factor. + * + * @param n node to be rebalanced + * @return new root after rebalancing + */ + private static RangeTreeNode rebalance(RangeTreeNode n) { + updateHeight(n); + int balance = getBalance(n); + if (balance < -1) { // right-heavy case + if (height(n.getRight().getLeft()) > height(n.getRight().getRight())) { + n.setRight(rotateRight(n.getRight())); + } + n = rotateLeft(n); + } else if (balance > 1) { // left-heavy case + if (height(n.getLeft().getRight()) > height(n.getLeft().getLeft())) { + n.setLeft(rotateLeft(n.getLeft())); + } + n = rotateRight(n); } + return n; + } - /** - * Deletes an element from the Range Tree while maintaining balance. - * - * @param node The root node of the Range Tree. - * @param val The value to be deleted. - * @return The root node of the updated Range Tree. - */ - public static RangeTreeNode delete(RangeTreeNode node, int val) { - if (node.getLeft().getLeft() == null && node.getLeft().getRight() == null - && val == node.getLeft().getVal()) { // left node is the leaf node - node.setVal(node.getRight().getVal()); - node.setLeft(null); - node.setRight(null); - } else if (node.getRight().getLeft() == null && node.getRight().getRight() == null - && val == node.getRight().getVal()) { // right node is the leaf node - node.setLeft(null); - node.setRight(null); - } else { - if (val <= node.getVal()) { - if (node.getLeft() != null) { - node.setLeft(delete(node.getLeft(), val)); - } - if (val == node.getVal()) { // duplicate node - node.setVal(getMostRight(node.getLeft()).getVal()); // update the duplicate key - } - } else { - if (node.getRight() != null) { - node.setRight(delete(node.getRight(), val)); - } - } + /** + * Deletes an element from the Range Tree while maintaining balance. + * + * @param node The root node of the Range Tree. + * @param val The value to be deleted. + * @return The root node of the updated Range Tree. + */ + public static RangeTreeNode delete(RangeTreeNode node, int val) { + if (node.getLeft().getLeft() == null && node.getLeft().getRight() == null + && val == node.getLeft().getVal()) { // left node is the leaf node + node.setVal(node.getRight().getVal()); + node.setLeft(null); + node.setRight(null); + } else if (node.getRight().getLeft() == null && node.getRight().getRight() == null + && val == node.getRight().getVal()) { // right node is the leaf node + node.setLeft(null); + node.setRight(null); + } else { + if (val <= node.getVal()) { + if (node.getLeft() != null) { + node.setLeft(delete(node.getLeft(), val)); } - return rebalance(node); - } - - /** - * Finds and returns the rightmost node in the Range Tree rooted at the given node. - * - * @param n The root node of a subtree to search in. - * @return The rightmost node in the subtree, or null if the input node is null. - */ - private static RangeTreeNode getMostRight(RangeTreeNode n) { - if (n.getRight() == null) { - return n; - } else { - return getMostRight(n.getRight()); + if (val == node.getVal()) { // duplicate node + node.setVal(getMostRight(node.getLeft()).getVal()); // update the duplicate key + } + } else { + if (node.getRight() != null) { + node.setRight(delete(node.getRight(), val)); } + } } + return rebalance(node); + } - /** - * Performs a level order traversal of the Range Tree and prints the elements. - * This is not a necessary function for orthogonal range searching, but merely a utility function for debugging - * and visualisation purposes. - * - * @param root The root node of the Range Tree. - */ - public static void levelOrderTraversal(RangeTreeNode root) { - if (root == null) { - return; - } + /** + * Finds and returns the rightmost node in the Range Tree rooted at the given node. + * + * @param n The root node of a subtree to search in. + * @return The rightmost node in the subtree, or null if the input node is null. + */ + private static RangeTreeNode getMostRight(RangeTreeNode n) { + if (n.getRight() == null) { + return n; + } else { + return getMostRight(n.getRight()); + } + } - Queue queue = new LinkedList<>(); - queue.add(root); - while (!queue.isEmpty()) { - RangeTreeNode current = queue.poll(); - System.out.print(current.getVal() + " "); - if (current.getLeft() != null) { - queue.add(current.getLeft()); - } - if (current.getRight() != null) { - queue.add(current.getRight()); - } - } + /** + * Performs a level order traversal of the Range Tree and prints the elements. + * This is not a necessary function for orthogonal range searching, but merely a utility function for debugging + * and visualisation purposes. + * + * @param root The root node of the Range Tree. + */ + public static void levelOrderTraversal(RangeTreeNode root) { + if (root == null) { + return; + } + Queue> queue = new LinkedList<>(); + queue.add(root); + while (!queue.isEmpty()) { + RangeTreeNode current = queue.poll(); + System.out.print(current.getVal() + " "); + if (current.getLeft() != null) { + queue.add(current.getLeft()); + } + if (current.getRight() != null) { + queue.add(current.getRight()); + } } + } } diff --git a/src/main/java/algorithms/orthogonalRangeSearching/oneDim/README.md b/src/main/java/algorithms/orthogonalRangeSearching/oneDim/README.md new file mode 100644 index 00000000..170d2ff6 --- /dev/null +++ b/src/main/java/algorithms/orthogonalRangeSearching/oneDim/README.md @@ -0,0 +1,13 @@ +# 1D Orthogonal Range Searching + +1D orthogonal range searching is a computational problem where you search for elements or data points within a +specified 1D range (interval) in a collection of 1D data (e.g. Find me everyone between ages 22 and 27). + +While we can simply sort (and binary search the low and high of the specified range) to return all data points within +the specified range, each query will minimally take O(nlogn) due to the sorting step, assuming dynamic updating of +the data. + +The goal of 1D Orthogonal Range Searching is to efficiently identify and retrieve all data points that fall within the +given range. + +####NOT DONE YET#### \ No newline at end of file diff --git a/src/main/java/algorithms/orthogonalRangeSearching/twoDim/OrthogonalRangeSearching.java b/src/main/java/algorithms/orthogonalRangeSearching/twoDim/OrthogonalRangeSearching.java new file mode 100644 index 00000000..8a60ea6a --- /dev/null +++ b/src/main/java/algorithms/orthogonalRangeSearching/twoDim/OrthogonalRangeSearching.java @@ -0,0 +1,314 @@ +package algorithms.orthogonalRangeSearching.twoDim; + +import algorithms.orthogonalRangeSearching.RangeTreeNode; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +public class OrthogonalRangeSearching { + + /** + * Builds the X-tree, a data structure for the given range of 2D points. + * + * @param inputs List of 2D points in the format Integer[], where each array + * represents a point with two coordinates (x, y). + * @param start The starting index of the current range. + * @param end The ending index of the current range. + * @return The root node of the X-tree for the specified range. + */ + public static RangeTreeNode buildXTree(List inputs, int start, int end) { + + int mid = (end + start) / 2; + inputs.sort(Comparator.comparingInt(a -> a[0])); + + if (start > end) { + return null; + } else if (end - start + 1 > 3) { + RangeTreeNode node = new RangeTreeNode<>(inputs.get(mid), buildXTree(inputs, start, mid), + buildXTree(inputs, mid + 1, end)); + node.setYTree(buildYTree(inputs, start, end)); + return node; + } else if (end - start + 1 == 3) { + RangeTreeNode node = new RangeTreeNode<>(inputs.get(mid), buildXTree(inputs, start, mid), + buildXTree(inputs, end, end)); + node.setYTree(buildYTree(inputs, start, end)); + return node; + } else if (end - start + 1 == 2) { + RangeTreeNode node = new RangeTreeNode<>(inputs.get(mid), + buildXTree(inputs, start, start), + buildXTree(inputs, end, end)); + node.setYTree(buildYTree(inputs, start, end)); + return node; + } else { + RangeTreeNode node = new RangeTreeNode<>(inputs.get(mid)); + node.setYTree(buildYTree(inputs, start, end)); + return node; + } + } + + /** + * Builds the Y-tree, a data structure for the given range of 2D points. + * + * @param inputs List of 2D points in the format Integer[], where each array + * represents a point with two coordinates (x, y). + * @param start The starting index of the current range. + * @param end The ending index of the current range. + * @return The root node of the Y-tree for the specified range. + */ + private static RangeTreeNode buildYTree(List inputs, int start, int end) { + + int mid = (end + start) / 2; + List ySortedSublist = inputs.subList(start, end + 1); + ySortedSublist.sort(Comparator.comparingInt(a -> a[1])); //sort by y-coordinate + + return buildYTreeHelper(ySortedSublist, 0, ySortedSublist.size() - 1); + } + + /** + * Helper function to build the Y-tree. + * + * @param inputs List of 2D points in the format Integer[], where each array + * represents a point with two coordinates (x, y). + * @param start The starting index of the current range. + * @param end The ending index of the current range. + * @return The root node of the Y-tree for the specified range. + */ + private static RangeTreeNode buildYTreeHelper(List inputs, int start, int end) { + + int mid = (end + start) / 2; + + if (start > end) { + return null; + } else if (end - start + 1 > 3) { + return new RangeTreeNode<>(inputs.get(mid), buildYTree(inputs, start, mid), + buildYTree(inputs, mid + 1, end)); + } else if (end - start + 1 == 3) { + return new RangeTreeNode<>(inputs.get(mid), buildYTree(inputs, start, mid), + buildYTree(inputs, end, end)); + } else if (end - start + 1 == 2) { + return new RangeTreeNode<>(inputs.get(mid), buildYTree(inputs, start, start), + buildYTree(inputs, end, end)); + } else { + return new RangeTreeNode<>(inputs.get(mid)); + } + } + + /** + * Finds the X-split node in the X-tree based on the specified X-coordinate range. + * + * @param root The root node of the X-tree. + * @param xLow The lower bound of the X-coordinate range. + * @param xHigh The upper bound of the X-coordinate range. + * @return The X-split node or null if not found. + */ + public static RangeTreeNode findXSplit(RangeTreeNode root, int xLow, int xHigh) { + RangeTreeNode v = root; + + while (true) { + if (v == null) { + return null; + } else { + if (xHigh <= v.getVal()[0]) { + v = v.getLeft(); + } else if (xLow > v.getVal()[0]) { + v = v.getRight(); + } else { + break; + } + } + } + return v; + } + /** + * Performs a left traversal of the X-tree to find points within the specified range. + * + * @param v The current node in the X-tree. + * @param xLow The lower bound of the X-coordinate range. + * @param xHigh The upper bound of the X-coordinate range. + * @param yLow The lower bound of the Y-coordinate range. + * @param yHigh The upper bound of the Y-coordinate range. + * @param result A list to store the results. + */ + public static void XLeftTraversal(RangeTreeNode v, int xLow, int xHigh, int yLow, int yHigh, + ArrayList result) { + if (v != null) { + if (v.getLeft() == null && v.getRight() == null && v.getVal()[0] >= xLow && v.getVal()[0] <= xHigh) { //leaf + YSearch(v, yLow, yHigh, result); + } else { + if (xLow <= v.getVal()[0]) { + XLeftTraversal(v.getLeft(), xLow, xHigh, yLow, yHigh, result); + YSearch(v.getRight(), yLow, yHigh, result); + } else { + XLeftTraversal(v.getRight(), xLow, xHigh, yLow, yHigh, result); + } + } + } + } + /** + * Performs a right traversal of the X-tree to find points within the specified range. + * + * @param v The current node in the X-tree. + * @param xLow The lower bound of the X-coordinate range. + * @param xHigh The upper bound of the X-coordinate range. + * @param yLow The lower bound of the Y-coordinate range. + * @param yHigh The upper bound of the Y-coordinate range. + * @param result A list to store the results. + */ + public static void XRightTraversal(RangeTreeNode v, int xLow, int xHigh, int yLow, int yHigh, + ArrayList result) { + if (v != null) { + if (v.getLeft() == null && v.getRight() == null && v.getVal()[0] >= xLow && v.getVal()[0] <= xHigh) { //leaf + YSearch(v, yLow, yHigh, result); + } else { + if (xHigh >= v.getVal()[0]) { + YSearch(v.getLeft(), yLow, yHigh, result); + XRightTraversal(v.getRight(), xLow, xHigh, yLow, yHigh, result); + } else { + XRightTraversal(v.getLeft(), xLow, xHigh, yLow, yHigh, result); + } + } + } + } + /** + * Finds the Y-split node in the X-tree based on the specified X-coordinate range. + * + * @param root The root node of the X-tree. + * @param yLow The lower bound of the X-coordinate range. + * @param yHigh The upper bound of the X-coordinate range. + * @return The X-split node or null if not found. + */ + public static RangeTreeNode findYSplit(RangeTreeNode root, int yLow, int yHigh) { + RangeTreeNode v = root; + + while (true) { + if (v == null) { + return null; + } else { + if (yHigh <= v.getVal()[1]) { + if (v.getLeft() == null && v.getRight() == null) { // extra check since ysplit might be leaf node + break; + } else { + v = v.getLeft(); + } + } else if (yLow > v.getVal()[1]) { + v = v.getRight(); + } else { + break; + } + } + } + return v; + } + + /** + * Performs a recursive traversal of the Range Tree and adds leaf node values to the result list. + * + * @param v The current node being processed during traversal. + * @param result The list to store the values of leaf nodes encountered during traversal. + */ + public static void allLeafTraversal(RangeTreeNode v, List result) { + if (v != null) { + if (v.getLeft() != null) { + allLeafTraversal(v.getLeft(), result); + } + if (v.getLeft() == null && v.getRight() == null) { // leaf + result.add(v.getVal()); + } + if (v.getRight() != null) { + allLeafTraversal(v.getRight(), result); + } + } + } + + /** + * Performs a left traversal of the Y-tree to find points within the specified range. + * + * @param v The current node in the Y-tree. + * @param low The lower bound of the Y-coordinate range. + * @param result A list to store the results. + */ + public static void leftTraversal(RangeTreeNode v, int low, List result) { + if (v != null) { + if (v.getLeft() == null && v.getRight() == null) { // leaf + result.add(v.getVal()); + } else { + if (low <= v.getVal()[1]) { + leftTraversal(v.getLeft(), low, result); + allLeafTraversal(v.getRight(), result); + } else { // definitely a qualifying leaf has to exist + leftTraversal(v.getRight(), low, result); + } + } + } + } + + /** + * Performs a right traversal of the Y-tree to find points within the specified range. + * + * @param v The current node in the Y-tree. + * @param high The upper bound of the Y-coordinate range. + * @param result A list to store the results. + */ + public static void rightTraversal(RangeTreeNode v, int high, List result) { + if (v != null) { + if (v.getLeft() == null && v.getRight() == null && v.getVal()[1] <= high) { // leaf, need extra check + result.add(v.getVal()); + } else { + if (high > v.getVal()[1]) { + allLeafTraversal(v.getLeft(), result); + rightTraversal(v.getRight(), high, result); + } else { // a qualifying leaf might or might not exist, we are just exploring + rightTraversal(v.getLeft(), high, result); + } + } + } + } + + /** + * Searches for 2D points within the specified Y-coordinate range in the Y-tree. + * + * @param v The root node of the Y-tree. + * @param yLow The lower bound of the Y-coordinate range. + * @param yHigh The upper bound of the Y-coordinate range. + * @param result A list to store the results. + */ + public static void YSearch(RangeTreeNode v, int yLow, int yHigh, ArrayList result) { + if (v != null) { + System.out.println(v.getVal()[0]); + RangeTreeNode splitNodeY = findYSplit(v.getYTree(), yLow, yHigh); + if (splitNodeY != null) { + if (splitNodeY.getLeft() == null && splitNodeY.getRight() == null + && splitNodeY.getVal()[1] >= yLow && splitNodeY.getVal()[1] <= yHigh) { // if split node is leaf + result.add(splitNodeY.getVal()); + } + leftTraversal(splitNodeY.getLeft(), yLow, result); + rightTraversal(splitNodeY.getRight(), yHigh, result); + } + } + } + + /** + * Searches for 2D points within the specified orthogonal range in the X-tree. + * + * @param tree The root node of the X-tree. + * @param xLow The lower bound of the X-coordinate range. + * @param xHigh The upper bound of the X-coordinate range. + * @param yLow The lower bound of the Y-coordinate range. + * @param yHigh The upper bound of the Y-coordinate range. + * @return A list of 2D points within the specified orthogonal range. + */ + public static List search(RangeTreeNode tree, int xLow, int xHigh, int yLow, int yHigh) { + RangeTreeNode splitNodeX = findXSplit(tree, xLow, xHigh); + ArrayList result = new ArrayList<>(); + if (splitNodeX != null) { //will split node ever be leaf.... possible if range is size 1 + if (splitNodeX.getLeft() == null && splitNodeX.getRight() == null + && splitNodeX.getVal()[0] >= xLow && splitNodeX.getVal()[0] <= xHigh) { // if split node is leaf + YSearch(splitNodeX, yLow, yHigh, result); + } + XLeftTraversal(splitNodeX.getLeft(), xLow, xHigh, yLow, yHigh, result); + XRightTraversal(splitNodeX.getRight(), xLow, xHigh, yLow, yHigh, result); + } + return result; + } +} diff --git a/src/test/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearchingTest.java b/src/test/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearchingTest.java index 7aff2eba..8ac057d3 100644 --- a/src/test/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearchingTest.java +++ b/src/test/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearchingTest.java @@ -39,24 +39,28 @@ public void test_OrthogonalRangeSearching() { Object[] fifthResult = OrthogonalRangeSearching.search(fourthTree, 31, 130); assertArrayEquals(fifthExpected, fifthResult); + Object[] sixthExpected = new Object[] {59}; + Object[] sixthResult = OrthogonalRangeSearching.search(fourthTree, 59, 59); + assertArrayEquals(sixthExpected, sixthResult); + // dynamic updates then query OrthogonalRangeSearching.configureTree(fourthTree); fourthTree = OrthogonalRangeSearching.insert(fourthTree, 101); - Object[] sixthExpected = new Object[] {49, 59, 70, 89, 100, 101}; - Object[] sixthResult = OrthogonalRangeSearching.search(fourthTree, 31, 130); - assertArrayEquals(sixthExpected, sixthResult); + Object[] seventhExpected = new Object[] {49, 59, 70, 89, 100, 101}; + Object[] seventhResult = OrthogonalRangeSearching.search(fourthTree, 31, 130); + assertArrayEquals(seventhExpected, seventhResult); fourthTree = OrthogonalRangeSearching.insert(fourthTree, 46); fourthTree = OrthogonalRangeSearching.insert(fourthTree, 32); - Object[] seventhExpected = new Object[] {30, 32, 46, 49, 59, 70}; - Object[] seventhResult = OrthogonalRangeSearching.search(fourthTree, 20, 71); - assertArrayEquals(seventhExpected, seventhResult); + Object[] eighthExpected = new Object[] {30, 32, 46, 49, 59, 70}; + Object[] eighthResult = OrthogonalRangeSearching.search(fourthTree, 20, 71); + assertArrayEquals(eighthExpected, eighthResult); fourthTree = OrthogonalRangeSearching.delete(fourthTree, 32); fourthTree = OrthogonalRangeSearching.delete(fourthTree, 59); - Object[] eighthExpected = new Object[] {30, 46, 49, 70}; - Object[] eighthResult = OrthogonalRangeSearching.search(fourthTree, 20, 72); - assertArrayEquals(eighthExpected, eighthResult); + Object[] ninthExpected = new Object[] {30, 46, 49, 70}; + Object[] ninthResult = OrthogonalRangeSearching.search(fourthTree, 20, 72); + assertArrayEquals(ninthExpected, ninthResult); } } diff --git a/src/test/java/algorithms/orthogonalRangeSearching/twoDim/OrthogonalRangeSearchingTest.java b/src/test/java/algorithms/orthogonalRangeSearching/twoDim/OrthogonalRangeSearchingTest.java new file mode 100644 index 00000000..d0f52e95 --- /dev/null +++ b/src/test/java/algorithms/orthogonalRangeSearching/twoDim/OrthogonalRangeSearchingTest.java @@ -0,0 +1,47 @@ +package algorithms.orthogonalRangeSearching.twoDim; + +import algorithms.orthogonalRangeSearching.RangeTreeNode; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertArrayEquals; + +public class OrthogonalRangeSearchingTest { + @Test + public void test_OrthogonalRangeSearching() { + + ArrayList firstInput = new ArrayList<>(); + firstInput.add(new Integer[] {4, 5}); + firstInput.add(new Integer[] {3, 3}); + firstInput.add(new Integer[] {2, 4}); + firstInput.add(new Integer[] {1, 2}); + firstInput.add(new Integer[] {5, 2}); + firstInput.add(new Integer[] {6, 3}); + firstInput.add(new Integer[] {7, 1}); + firstInput.add(new Integer[] {8, 4}); + + ArrayList firstExpected = new ArrayList<>(); + firstExpected.add(new Integer[] {1, 2}); + firstExpected.add(new Integer[] {3, 3}); + firstExpected.add(new Integer[] {5, 2}); + firstExpected.add(new Integer[] {6, 3}); + + RangeTreeNode firstTree = OrthogonalRangeSearching.buildXTree(firstInput, + 0, firstInput.size() - 1); + List firstResult = OrthogonalRangeSearching.search(firstTree, 1, 6,1, 3); + assertArrayEquals(firstExpected.toArray(), firstResult.toArray()); + + ArrayList secondExpected = new ArrayList<>(); + secondExpected.add(new Integer[] {6, 3}); + secondExpected.add(new Integer[] {7, 1}); + secondExpected.add(new Integer[] {8, 4}); + List secondResult = OrthogonalRangeSearching.search(firstTree, 6, 9,0, 4); + assertArrayEquals(secondExpected.toArray(), secondResult.toArray()); + + ArrayList thirdExpected = new ArrayList<>(); + List thirdResult = OrthogonalRangeSearching.search(firstTree, 6, 9,2, 2); + assertArrayEquals(thirdExpected.toArray(), thirdResult.toArray()); + } +} From b3235020fff074a945b7b3254610203613012071 Mon Sep 17 00:00:00 2001 From: kaitinghh <114789615+kaitinghh@users.noreply.github.com> Date: Fri, 22 Dec 2023 15:56:23 +0800 Subject: [PATCH 05/51] update profile --- docs/team/profiles.md | 2 +- .../orthogonalRangeSearching/oneDim/README.md | 21 ++++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/docs/team/profiles.md b/docs/team/profiles.md index 3848e26b..837fb910 100644 --- a/docs/team/profiles.md +++ b/docs/team/profiles.md @@ -3,7 +3,7 @@ | Name | Description/About | Website (LinkedIn/GitHub/Personal) | Contributions | |-----------|--------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------| | Andre | An aspiring ML engineer. My stint as a CS2040s TA has convinced several capable and passionate students to join me in developing this project :) | You can find me [here](https://4ndrelim.github.io) as well! | Team lead | -| Kai ting | ... | ... | Trees and Sorts! All sorts!
Bubble, Insertion, Selection, Merge, Quick | +| Kai Ting | Aspiring algorithm/ML engineer. | [Linkedin](https://www.linkedin.com/in/kai-ting-ho-425181268/) | Trees and Sorts! All sorts!
Bubble, Insertion, Selection, Merge, Quick | | Changxian | ... | ... | Tricky Hashing and its variants | | Owen | ... | ... | Graphs and confusing mazes | | Shu Heng | Interested in ML, aspiring researcher. | No website but here's my [Linkedin](https://www.linkedin.com/in/yeoshuheng), please give me a job :< | Fundamentals! Linked List and its variants, Stacks & Queues and their variants | diff --git a/src/main/java/algorithms/orthogonalRangeSearching/oneDim/README.md b/src/main/java/algorithms/orthogonalRangeSearching/oneDim/README.md index 170d2ff6..cf6df9c1 100644 --- a/src/main/java/algorithms/orthogonalRangeSearching/oneDim/README.md +++ b/src/main/java/algorithms/orthogonalRangeSearching/oneDim/README.md @@ -10,4 +10,23 @@ the data. The goal of 1D Orthogonal Range Searching is to efficiently identify and retrieve all data points that fall within the given range. -####NOT DONE YET#### \ No newline at end of file + +![InsertionSort](../../../../../../docs/assets/images/InsertionSort.png) + +## Complexity Analysis +**Time**: +- Overall: + +- Build Tree (cost incurred once only): O(nlogn) limited by sorting step + +Querying: O(k + logn) +- Find Split Node: O(logn) (binary search) +- Left Traversal: at every step, we either + 1. output all-right subtree (O(k) where k is no. of leaves) and recurse left + 2. recurse right (at most logn times) +- Right Traversal: similar to left traversal + +**Space**: S(n) = S(n / 2) + O(n) => O(nlogn) + +## Notes +### Common Misconception \ No newline at end of file From 15c79cf8a89ecb6799bdd8ae00300e7873ed79ae Mon Sep 17 00:00:00 2001 From: kaitinghh <114789615+kaitinghh@users.noreply.github.com> Date: Sat, 23 Dec 2023 21:55:26 +0800 Subject: [PATCH 06/51] update 1d ors readme --- docs/assets/images/1DORS.jpg | Bin 0 -> 114648 bytes docs/assets/images/1DORSDynamicUpdates.jpg | Bin 0 -> 82642 bytes docs/assets/images/1DORSQuery.jpeg | Bin 0 -> 74399 bytes .../orthogonalRangeSearching/oneDim/README.md | 30 +++++++++++++++--- 4 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 docs/assets/images/1DORS.jpg create mode 100644 docs/assets/images/1DORSDynamicUpdates.jpg create mode 100644 docs/assets/images/1DORSQuery.jpeg diff --git a/docs/assets/images/1DORS.jpg b/docs/assets/images/1DORS.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2ab8879229880b2be55b6eee70a7906bfcb159ca GIT binary patch literal 114648 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�j_%t#H`mhD70(@#pYM@Wfx4Tc&GJ?1)nu4er0$$<^7#eTkP2K)&7 zuogmY?X=YpncLn6;=J~fdljcq*QXydbJ2Dae@c^%wE2lm-nI8$5fnSQgzggpVcIW6 zcNj=1{lr2=`ptNOL(e8x)nXPJjo%v&X&7(!`_fAyoKWaYueiMafMR;she6KMRFjFW z>VAD$fNUACy*;GbbD-MN#^RZLhM6N{)CM89=_3o(^WIZTSU_+@J_aeQ-tRr5JxmJ^ zm{(~qBE;2lA9v(gmKsc>YugwPSDgVMj-S4f(b5+ugKH(RoNGjSW~oALynM6tx^+Eu ziHM9^hh*#`y3fpCc=F1Gp8DIM!dLM^fw=<5v`qXxw9Q*zj6+-1Z(9ygy8?z3r9BQC zAq2bMZe&HRA5z#p>--VAo!apUiOnLLGblR>rVFJj**DMIMN6eTQ>*#ae|Og6vxAk z$~rVeO_9e4@Ic=WE+(!_4(@ms0|c^@0?U^&sVqVr@xV7jEIsIfdoG6sD}Ung%4FMt zpiZ6-m96UTr_Filw5g*eihq;IyYL+mb^Dd$w?8w}+4@HP!F4I()yzCnntcHBh^_!E z#R@~dhGEj9?l19vuT2JY-8|(hHz-x4D23#@T-X|a4_|4$WX(s5Q(ZXN7MVqkq-s`F zeyVYH#?M0$Td3kbeN@_MJXpzN|-6DHzTy9-rB=f8O|;3(>zSKYR>`N`L{Qg&WF zJ((>}`I3aCcX!&z7mZesCJToJtHjlJ&~ViRVH8q#Tl;$aFe|B~X|D@0w@1CMu5vpm z%2$=rqJF&ce5xVO(biV`GaA<-i?awHSUx+G<+Oui9S`L<_XW&13<-ky4yXv|^yxe- zxL!9yKiS>pMA)P_ap&>F;mH#rO0VWG1QHg50~VagOxxN51y(*{M4Qt?v}m=J{rm@y zj1|A7eUEc|Q?61^d@)=QdiCNht}THUH@UWPaj&EX!<`Vrn^Rf>C)oFk!dBZZEVk#x zIVhLJEapCQ<=b_BrR5w?qWNFcrlw33JZq>aX6QCp~ z%V(!>$HHcI22`3qAg>ZZ%e}4^#kXMmoWY)$>vGa=-5>?EMoRxQevwV6AFH7-4a@F> zA;`ssSadV>ByCg{FHA<6 zZUhA{1?rQA>L$}vrjyYy@q-gCt)oo^rB)sBx`{-IJ1pre>-d$J;#EIcnQoX<)zD^l zx5Kyb3qUWH99Y`>56>%0tyWS71aJtN_C+~kAH9kK*gDikzG?e0QmEMeL&?@QsN6=l zIt*f%EX}KLwI50}FonaJV?nVxc=?a%L)k3DQpC0}>U z(}A_a1lCR?Y6+~B22psT%^sYi(PeDy0vG`O>ZjF6h*tyypwl{*WLKqMah`x1auM9F zn8>ZClhEWP9>Q~&c8R>v&O{IunyM*?4taA#MfYHj{*`1q51-yu?|tIU3{K6i5Mg-` z9>O#;@>qvCH3_n`mr9$Bl}Su;D;u}${9^YSaa6m8kc&(X^>LSpqrYO zTx8vr4kMr9qln1$axhY7!#*Ena|=uxBT6D-u)L9U1Xi;Bt@0 z)~4=*nY^=wOvBAr$)qpQ99)$HnP1|dv(e4vu|3!0dfrd;YT2^YaQan6@_HN6-g$qY z?VyYlKrhHEeEMP9xl?y=n|#_?>#1;>yW5#o$KkdaCqZ&zPfSJM$(3JvmNy>iy+7D_ zyqka4l00S1IKxRm)z}xkRsvtK1_X>X8OPJAE`Dz<7!@X?CE&uU-w#LQH0>X!9 zm(dOHE4%xG*@6YH(iIdX3ImC=)5|V<<&Qh*u|2XsAszTfFSG>H42ly{i_T~(Dcsho z_GX|;Ru;Rp>?W3Z|uVd>G@^5GB{V6#D#od zjZzfZ+5b4h|6RZT8sz%#MqB?`9_qi*_XFhTMu0^1-Mb$JtnK?AwdN$i9hap|7>UH) zBMOsuW9_+kTc*GNa?BsLj9h@Gne46DXVCi~^JhK)bc(FFShks5jpx6en*Y8Ivww9p zC;{&*e9F9_TJ&RwES~}x>eRmx$qI9R&aqi1CgB`nB|PJ)w`4gW(CG~gmV;6;x+#g()f*|BOaR$C}0rkN?5azSV)nxV>cM$&7 zvu7Cc!y_Q&-to{&Rva!FpiT`z+48`D+oCc3Ylr&Ze7R3Pd;5=31Fq(hNO^kPaB-q4 zO1H?j(5FAF&?l|0_7HFA8r@PF`4EZ+V4!zC?+jz8=sxCLP+tefteU-z39nN|%&;S6 zLU7%Oqg0O1B+R;g7kfFy^g@8$tiUz-gKLQmLK_n=rdWQINqFNAuHXkif9>TM4j4!y zsj%-3fR!54`HCY0$NfBYbzvBEg&4>(vn!oZ+}Vofj%4#x;ZN(JE2YRcKxBOlfiBro zP0a~*-!8U*%4L}M?3F*kbUSIjtECZbF4J-F4B|X$ck!03I;zzXury^mr$~I|=^5l@9SIe)L^6qn7_s@y{& zcPe5zc6sjtY!m(}OHYVj)4EG3{~x!WFUD6FPs-YI5h_<)RHIS518K!_Z9MvY#x zTrSDeG}=}sVG`rv66|SOuV#9kDC6~M&&igP4g2d$1P}P*CO@o-Sm^&i?V@7*XV^Hq zc9u?g=>}7~!(zU6d5dJ7Vqe{B-AT!-HFxo)oEv=D#w}1J!nxjL@m;7YXfZqd1IHrf z&9kq{gu|JXd9?{=rBgnH`BStM-&Uzo}U9vt|yl=;gtI{tcxNn~GkQX$(QK}`v z?9p%lME}Kod1f8R{&3eq3}rwseHouC;1#mrdEGKaxYHEStw{(!iK|6q-XZIT-FKLO z_JUGr$1pbpA4pXj+_ZaSK< zyhNxe{VG{oEBNSKe1qovoVdF|7V(L}!)+EfZy1@+B$a)i8M8t_vcb<2BpiH@B+y&R zgouR}Q6~AQQ9zwgF&%(+BP@-AsKIzo5cV>i6;MrNN?uqbVNXbd8i0~MjZYdC%lDGP!f12n3hJhUvjK6t00gs#}mlP=bB3M*x&)n^>vik)gjl_BV>XbL0qxl0vb; zRlj>CADtAKHWE?1q~j!YxT-D4U$<9^sTGW^1>qK+L&!djLR!=SKKLqu*Zv7vW2nK{ zeob;n=>4qiwa+uGnAgs)U&FjrDZ*9;Hsp68(>%v<*&X-iM%t7U+e<8m1eMu(EE$DW z&eczzwU^%`D(T9^-n*tM^UDPzmX6k4j}F{*@kv3!i=Wg8k*3i-1eT7$VWQE9W1qTkVY76c z(q1k~le(&FdJvEW2RMRBgU<_(roz%xO;#0h*-EBAWcv%9dMAn$+^?oHspXBgfN9GW zycMj=p4l25&VIX~2kV0oH!$oE{}R8zyU}VmuSEU;eUu1RY z$}G!_FaEUBrI!99PeS2C8j?OXbxmy~Mcx)-+eBjdv-xr9cCOK1Q9zEpKUwd4zwNhfX!-wPiNm)?$C zAP$di218MnG7ibFKM-=qki{;>wTgh_!{uekYywnP-~<3LlH;5&!(uZnbEYhA$Z_S| zO!T#7&j;(bxt>`S5;PsWy}QRZcE7Ut7jIeiZd3&crnxb0(?}I_!4i2U->I)IDJ6Xw zQ44X{K$hF^Hhpi9QaGk$+fbWPa$UGi>vZ2q4N1#LR`;`mx^f~ zeIETJ=s{9Kmn+`_973Kyat$!zP9H#65t#lBHj-7PH7+;i$+Pv*tr_toTOn-0W!UK^%SY|~stMT@PU zns`5%4wB(Z?7UEi5kBXTFHz)68y1CpRUNH2U)Wl_JYvEsCDhFsZvP2VW4-+EvM~Q~ z-@j&Q{@okwuUncgz=2Fdr0Dv?bJP4oIBs-XQ4?cOllqIL zt$UWXX*eF@Eor@`Iok7jK(t;|4X<|o)?J(F{pv6cPg~zLjE@L1igv=HB}J{t zn)_-jrB1{~DYm$U=0TL7>6K_w`@h-wzs6#xPKt_l$AuJoch3e{%U5=SZX)udB1RDg z<6rZ|&-*2-xGWZiqX#V9LB+}nXrNS5j!vlFX3?+Hl=nr)D9pYm;;qcW!8c**@jWk| z3f?BX1N52~?8IY1J^;J`lYVdsSwyl8;PQ>o)&B0>VGRnsr6AZgG~^Dl#S0Ru z9#(1RLk11@x&{>lqYWdoQZ$^H#rrs(+0300rb>nLY9P7q!8@%0fWwd`Xd(*o9*+_+ z$>VH3V0{`k{@|Je@vb5Jug2KAJdQsv>x)};?S!W-#As}*2J+q!D2B5dj#f1~6DgNT zoSZCK@=cKGiCThb!tTOlBzLA$<^pNljqv-o)j`$$7$N{JLw*I)=feOp)dAMO;Tv$G z7RBgMn1BNaRj-bP26`x+yqIs0doG75SV6Z2S8p2;SBZv zSUfajzK{9^0geOo2NI;tfY(dJWmkVrkUK?r|Kmjw2u%f(<11)WE_#{DyN(8i)P4H>Jjx^rlV1zJ4Wwn#!XJ=rVZ zU+o=d4=0FvW$qp|8-ITZT8RpTF^Afnsz+zqlT_n}@FzQi^rUS!im9D=Ie9ypexOfo zkaby7LAm}$YwVONbXQKM4lN<|sN(&cFR2^gmd_>|Jb995v25;{J3R>w;cCbXoW*;; z{(&AeJm{wxP!Of4=|@BT8>-pI+%5ERGrXe9Vg*r0WvcMbrnyW5-}#Hy#zom%jNVmp zY4d{IQw0_5RRla%!v?qwm`<4<3gQe=Nu8`_MkLKeX3y+;FtW^uDFXA{y8GmNTtCJQ zC`GP;P;e-aBZo0BB6Yq4%x-`N34jSdQ5S|mIN})<>0mf(0WxfC5dy_;;_y%K7gGv{ z-0zaLS=IsR7bpaDYy#)}77<1I;ZX{95dM>;Kto5b!sFaPW%%|3XAno{erwP$3k1SW zSR8zr0{CF0pGhwR2ps}y3l235z#_Wgbu}Hpj2}=W7M)@p(RAXe zX#m^sk@iUgzkbt$O6%a>ZznC|xD#()cz7IDKxhaZCs%5f? zd!k9}62DrHlJT@qW>(Uz4#?(?e8&6zBKPXzUWO^Kg%ip;e36AM;pbD;C4$E;-q4$x zZDeLi4XR7p@oYWUlV3Jd0ENPc8-Q8$V*x#6R1WNYz#YH&|qrMGNn1zSb zzmpdQ0l|5|hZ={m?O*j#Ks6a4U<`)|U^ou=WEs>NF~ElL0hC)WOe4T7oD)n-qD&_Q zLBILFAmVpKd7g?!{p6p2;rT!5wh#?B9>bwxU?-phXco z8m2mUTv$)!{1vXfTnu5B!onWeA%}~^(0Da*&V*}|f^?omAp3Jfz|9xlkd42ud2eKY z`Xr#a7k$S6|8xPupWW~8c8I@^L;n5uzc!og&-Ur>hGT!WD}P`6>m2o$IO*@6K)(tb u{LO8@<+i`XNq@K4_?we{COZH0=Pz;6-^H8%WEcP0?*9LD{V#D+*Z%+t_XG+6 literal 0 HcmV?d00001 diff --git a/docs/assets/images/1DORSDynamicUpdates.jpg b/docs/assets/images/1DORSDynamicUpdates.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4c991658dabc168676f259f4f35238e563d858c5 GIT binary patch literal 82642 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

$Qt1P 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 RhyMT|KluUw0FFP(|Jjl{!2bXM literal 0 HcmV?d00001 diff --git a/src/main/java/algorithms/orthogonalRangeSearching/oneDim/README.md b/src/main/java/algorithms/orthogonalRangeSearching/oneDim/README.md index cf6df9c1..1450dbff 100644 --- a/src/main/java/algorithms/orthogonalRangeSearching/oneDim/README.md +++ b/src/main/java/algorithms/orthogonalRangeSearching/oneDim/README.md @@ -10,14 +10,25 @@ the data. The goal of 1D Orthogonal Range Searching is to efficiently identify and retrieve all data points that fall within the given range. +Strategy: +1. Use a binary search tree +2. Store all points in the leaves of the tree (internal nodes only store copies) +3. Each internal node v stores the MAX of any leaf in the left sub-tree (**ORS tree property**) -![InsertionSort](../../../../../../docs/assets/images/InsertionSort.png) +![1DORS](../../../../../../docs/assets/images/1DORS.jpg) + +Say we want to find all the nodes between 10 and 50 i.e. query(10, 50). We would want to: +1. Find split node: highest node where search includes both left & right subtrees +=> we want to make use of the ORS tree property to perform binary search to find our split node. See findSplit(root, low, high) in code. +2. Left traversal & right traversal + +![1DORSQuery](../../../../../../docs/assets/images/1DORSQuery.jpeg) +Image Source: Lecture Slides ## Complexity Analysis **Time**: -- Overall: -- Build Tree (cost incurred once only): O(nlogn) limited by sorting step +Build Tree (cost incurred once only): O(nlogn) limited by sorting step Querying: O(k + logn) - Find Split Node: O(logn) (binary search) @@ -29,4 +40,15 @@ Querying: O(k + logn) **Space**: S(n) = S(n / 2) + O(n) => O(nlogn) ## Notes -### Common Misconception \ No newline at end of file +### Dynamic Updates +If we need to dynamically update the tree, insertion and deletion is done in a manner similar to AVL trees +(insert/delete and rotate to maintain height balance), except now we need to ensure that we are adding the new node +as a leaf node, and we still need to adhere to the ORS tree property. + +Note how the ORS tree property enables efficient dynamic updating of the tree, as the value of the nodes do not need +to change after rotation. + +![1DORSDynamicUpdates](../../../../../../docs/assets/images/1DORSDynamicUpdates.jpg) + +For more implementation details, refer to the code below "// Functions from here onwards are designed to support +dynamic updates." From 32f6b34b8190d97d05c6f92710fae2927238bbb4 Mon Sep 17 00:00:00 2001 From: kaitinghh <114789615+kaitinghh@users.noreply.github.com> Date: Sat, 23 Dec 2023 23:00:47 +0800 Subject: [PATCH 07/51] update 2d ors readme --- docs/assets/images/2DORS.jpg | Bin 0 -> 112888 bytes docs/assets/images/2DORSQuery.jpg | Bin 0 -> 130343 bytes docs/assets/images/2DORSTrees.jpg | Bin 0 -> 157854 bytes .../orthogonalRangeSearching/oneDim/README.md | 6 +- .../twoDim/OrthogonalRangeSearching.java | 2 +- .../orthogonalRangeSearching/twoDim/README.md | 68 ++++++++++++++++++ 6 files changed, 72 insertions(+), 4 deletions(-) create mode 100644 docs/assets/images/2DORS.jpg create mode 100644 docs/assets/images/2DORSQuery.jpg create mode 100644 docs/assets/images/2DORSTrees.jpg create mode 100644 src/main/java/algorithms/orthogonalRangeSearching/twoDim/README.md diff --git a/docs/assets/images/2DORS.jpg b/docs/assets/images/2DORS.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4f43453b3bc5d2b592f0fb9c24f9ccde1613e690 GIT binary patch literal 112888 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 E1J5$~$N&HU literal 0 HcmV?d00001 diff --git a/docs/assets/images/2DORSQuery.jpg b/docs/assets/images/2DORSQuery.jpg new file mode 100644 index 0000000000000000000000000000000000000000..710b1f3948d8137b23f4b8d9b2e4736ad609b8e4 GIT binary patch literal 130343 zcmc$`2S5|e);GTNrXbRb1O*idy$I3*Dj*^PB3+2|CQU#`d=0vT&Qm z1o#4gl@*`}001|@$+8z<11T2p4`7i5IDVr6z=1{Tue3Xh!k^2q0syPf-^wQk0PKG* z58m^)bn4IF|8(TJ2LN2)8Fn=d4fT6$0C+th4Cd(!mOq_mVPymE-};T-3!Yys_)B?p zHMIhkzdfmd^)FB24l7{$3(a}Hi1W{7z>9w+4K)o-J#`H|4NX}M4LwaYJuPj(#O{QJ z1^Ant*JU4{kO=?KNC4Quvnp7eI03ggXKiM2#uQ)yThA))5f*moSA&8>A}^maKQ8O! z>>|tc`A>cG>+T+25n(1aHfMg(e>wi5|CT6|zxojX#+85FYn4%$uA5}u9bDILeHAON z`nPibkmB|BiSPn{p@Uh?E9^2@PZlMRwuz1m`$flrwD4uHQXma>EFkRnC%Wht?fECV z>9;cH&z%6vyaQ=jFMkhjkX{98CC|S*@Ar3f@TI6<&;6Bt)qa;xh`k+n{Pm`!fs;T0 z5CMb%mjDkS7LWyO0L_0=UhB8=CxB3}bS!Wgyv`5s2O`01Ou#e0?%)H`7C;E#1*iZ@ zAguwYfm!2MKZDnTi8Ar${!{wfxx@tkFvRTa?6m&v+-VE|ROIDd+-#ARhp{ zX%6$a?D5;}esMOdFUXtgB>=G7832Svz-wG1d^I(G`<-RiaRA_$-`UwX1Tx+O0ASqP z*`Yn(*6(MTU9)F1@vXQ2Ptf zfWHze_|L}5%F4#h1}1h6_FsvEljFC<`RBy-TjKtec>bDxyPB1i9sK9v z*w|Rv**L)Zg1^N78r1B99DDbxn{W!*dT<>G7uL9u@r+yUcy*`9xlxk5rsw4Z9$rx~ zaS6$ThYl+oQPk2ts-t^M@5D({GxJjxr|r($J2-+b*2~++*Uvv7Fd{PQN_0%@)x?`g zw~}wCq~3q{sX9Yhugg5iWE<;|90z@r-BHojh`y=SU)+mq&R;<+TgD)2|=5{;}l!uJnm0lGeN`;Lyrt@6I~liom`rph_) z010;xgIE~xnAmFWwMt_HxY9L3zt&SpOP{*`TK
3ON$>2 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

IfnBR|EpN{bsm zcsAZ2U@W!d@P!4x8aR2M^MvXk-G1AgfJ%qRz?1ao*#~ttX3!w89%8;p)^TDC5}ezy}4O1evdmB--yP3v+gH%thrVwU82{WzUdQY{Z-~rjNh#R()n*Sly5-M^b=Lu=S{UQv0CKe+@SEd=! zxhCr8E|Y`hG1k>CSr^3zBWU%|ABQ^5fzyB;v-7Is>Rnv0Yro3`ZqmS-;QF9!-tE=a z>xa8k*3Q^)ee(mcdoCv`TbD~{Vx9f@y77WjayDurHWyjkhHM&T2kXK_(IfvwtNT0A z&SAL{^F3HT!M54?l-vsZA*Py<-MuigM#&>@uFe!_oIqB*i?fjTVq+RPrROIhs@$M; zCy(?~9oNAYa%hp0K`g)nO+9kBdw5nw>ajd&EtP;W`QTx{<#`?k)x7dni-lp?CG4G; zlhZ7~8k05KCnH=<*3L7i_TwZz!cHi_I(cMiwt$q9o|5ZDMuA`W|*T6?OkW}eH=GLT_E}J*k+FZ+H8i~O{ zq3p|k?BUL_$Ib3XTNruz8kbf#N*oRyY{fwmF{B9eDhj{SGtN|}>h#F$_LGf&zVLQJ z*=}w?{1Al1E!i=wLfX*lT@=;doqYKPC2&q_)O`oIu`%5N9V~T>37j~0pV?TCS`JL5 zGZ=YDTv`4r7}1vS1a=F~#ysE>*s&jDel6H2C}>ckc>Q7POV4%g6Ey|O^%nZ)@2T;i zM-;bSb}RKP9$u|J|MB3=i~NtnUVLeV?gl^Pi`sIK_iRl?x*{_Mm26IqzwZ=e@%7aO z_>1yhJ8oU0ds3g#jGV!RAW^6^xWEtXR%%cHA)k0E^35B;xqw%29`AJZ*QdSZ?7Oil!IPbAcPy0O>{bz>vo<1&FO(PT2 z-Bf5fvh#p}^&*5ScW{Ad_0oT8Z`|>YiA!;(mCqdwx`X8BxaM=ak3}w~iFTM z5dl%fy-_c)?E}J^)7X!1vhK@Xf+(G6IA|!4ozVyVnTOd^<|>r&d3?KwsCVwZwRt^Z zxq92+$mqLQ>J;*(?}LW9$JDnp8L&2d7_ZRjZi0IT%{WHDhOE+zSLQ#K^=?J%%5bRg zgPswC3X%HCX62>U@>{<4@57r|4Kb8$MkUfql_#JvA6!F46d^dZslTK#)+FU7xI@t%1XVSvrNKof*sDlTaaO)h?!pV9fq zXN~K|Q;h*jx*?6eic|-qVjwp$Y;`E?hCTR@AY`YRf%a#Yg%!{FF8k)3(bald@aV}h z17#`ghGId%^k=iHt4*}-?I^JDT8#UbE)2;6B|?o@oT8tOj2HX?4Nz8o&BMsw_p`q3 z3V~KybF#$_}dCBLfk;U$g7TH3^RvB`%Lg zHHJ{iS)*RN^!O}KFSoPnC@s%5;qlbZmL(c=)G*aOEzdda`LZrnWvD{m`73SqC+vPG zFX9aZv=CA-xFjr^7>quyg-&TX)UKUbRY)llo_`mzXj)Cvgk{Rol#=>-_Nt808aTPe z>4vy9A?65-6k=A57ZBxYezGW*o`#jesAz2-t+tW`@0b<1okmPg9Au*!L&U(!>tb+E zVRaa~aE=pQs$j*cFb)jAE*J|GYt)Rr=W=0A-q$w3TRb+~&Q#LpRaw1bTq17?&6x25 z>5WQ8vLkW#7X)EG3ki~EN=}a&h?Vm}qhx}IhI(ua-)2&-d*=mYUkkR)(zR#fHSEy9 zUp;n3C5vN$Q%^Tz2TT8~V7L_?Y>jAhK&J4cS?9m7_le>4i=;5+l1MS}ziOgzI35)!UYrJupt#?%f;>Ji?=Sq*3aWH@i1K8ye9HC z4j^`x={@BxFnV)nMav=F{KyW_F;M{qb*LCZWRyS$8=|`#B7^ubpPha8>pB~Tg@wnte-vM<)3Q902u}}5W@wkaZNiw zgIEfJlfJi+s!7U$YxcS8g_k(LPTtG$WJyJRSeRw2n+6Z+02kIIyZ}ed8Tv7rRt#(i z$rh*A>{@B|O?qqZ>7qSF>HOU270pv4*0+8@gAWazF!kd#OVy>Nifuc75u@)Nq-c*J zeFSD2Pu5QapNK)*H(Iuz{busmC6@CG2g*PQUe;XD*lw_05g>27F`l9NA=BC2;VYo=-a|9J`!e(yELKufK|?=`1JM+l zSPX_gyfVM@9W?D1s8CcdWJcpteD*1_5HcuWc~rgLgm1PId5+V#mW0>=*hpX?g`)0T z1)Zp}f4#_}e8X%wp}o9UnB}S5<8><5Jn&Oo__JQT0M9o)!yc%do6DfgnCAUA#*84$ z%faS@HuFyJL0C`|NwR=o2m3HwOr4l1CJ&ir{!u#*T@XS0X#7?9f~Se$XK-@U>59zm10qo2cKXiK^Ms_NrT)H@Q@>Drl-9~^%+ z(%C4!9s3y-NL(STdUzG?BTHQ)Sn3WuryW6d z)}C9K??BHC77bVv$>SIryywh`O#!Tzfw>_j;maKzzx5=jk znDO27`CF=k@2GFX5m50hja2Eut>Pji`dj}yNP{C?Ob+iy9Icp*+Xdo0yQc$r;Y8?&y4 zl(Ead%N{dc4hoOBJnz#pf4vj#Ohip8Fhx=Ex z((A03BJ%j&g*)X~3K{t+V;$1YeQoWSMP^%oLk*lz5(L3;_4`o}Zp0`?Qd^4Xh0n^A z`dDA2Y1U$ObED7B^MLthD|v;bGj~<9hBg#;9YKFRn+n|;za8^HBFEFH_HMowhQ0OR zD5TQI*$l#AIlWlu4NBY?zoJ;K-q0Bu&adBLET3S0Qwu4wj~7|DyaQkx!sZw`c4>9) zfemxBj$zXK3gvE~+yRywuZ8OzYSG6`k6WA8d~N5xtMKAe)=LoheDmtJ)f_iKv!QYR z!1yn3@D3pHg;byL%~5&L>iFTL8rIoC!Sv4_=_KQ^)9p2h2968%k1PFK%y0h)!tk$9 zM%}03U6iS#8wxQ?x9k>&u)AGUJ?U6JCE|pmP(HDe}Dfff=@Lm*ksB5NP3@jdAa` zZ=v~Mk8hmWu)14Nmn|UwTdHvbcJYnG}H>&mAp zB8j8%2&BfP|ZcH1{ERtc7R$@)S|uB_WKga`9PtJ4TGAy{V>pVyKGfl=TP22 zPTTTIo9y)gH!rZ}unI_j2-N+H;73y>OO4gQ8$`AQp1yd+C1Do&dvKPuW(oxUf){ZG z7%o^4jLT0it2lI#R%enhsOc90u?}QrtP-vy=v?yhmt_PIkhA%VeHjE8>(}`slL@!u z4wso$h=wk%2Ynj`Rwx~ZNr=a2tXd3O*1{(Jk%#fVSIa}n|2z)wuV{*WNm3E8zrWHM zT&$~F$7gtU(h}O^kQ&}#FSnNd$Y_H8F))93$1lTcKe(C0Tg1_i-);$T#9eA;4!apZ zRHO`zbJuiU@Z!8u8SS9n9E_QPQw&Eyg#&b4N(L|?SFA`gnqc5#dVX{5O@r^6eYhv) zmpPCU;L1Q06?*tO5?8c+C6^?HOYW|isl2pyvq3VK?E9hUQ6x<{w`xu4Y1oGa8D3U*oa-$n+}$=i&9{jTwwEE=4@QTFSuN+7irv3|Ex&mBwtwwW9!uagli@bfc#)q>w zs-xTDZi`Q}DmFyTTygI~xy*Z0IP=v28b1Qm9ze%V>XZy8b%=b(jUUFvUZ1nze(gyG z&7TB|@+)aRX$*W(-LrNJz0yrN0m?!pW*4kRwtgxSy$dBy%~=RSUZSQQ{8UQdiWFTk ztrLfZ-&a-R-*u~FoFT+ctoD17=^(&GqCJUY8~9ZoXx z+pywFgy9-tB+xRXfBlY570tR=jre=9)dee0l1H_ z87Qu)o(v=IyB1E?cS8j|2{5S{lM7G05iBL)i;ZEdzR=m{2}a2uVUy-{S&u-8M)1~k zRAl#hEF+b*L)+Ijoz@1aQaoo7v%+)Eo7r2)?x$0UbTJ(0cj%C=Cq-Y6tS}ThRc)<; z9q8gFRxZN7_Y0pcEu3a?Qxh@c5C2UuhC^C`QYqb#>+|IQppW)>g;1Yq5nebc2NoO z;6a2@^*m=QSk>E_&vlPil5z&-%4f~)xb~Ip`qWAJ6giW68*mFdj+nL1(4-D2swrvQ zoWzxQQS^#r{L8SSQvhEb{{(T5cMrJwlvQ}2qRanz^BRE!46fwr+*&g7A|_RD{t?ry zw<;-I{*wM4-6|m_j~f|jOC6>O#Xx(qt6uoOJdjkxCHv4=fB?5ZOe0v}AdFfIzuU%k zAofoAvR!B6)a5Ds8eQrM9(o5dBj--FD09;$uHB-WA~`3I&FmelcbryHVB0oGyMO&v zuf-XZ6z7p2Kr;6E*0(@~lT9C!KNoLppRcn~Ij&@A;McB~%2{|3oU9c7#y8ENGnZQ1 z)xkkxOx-aEF2nk7+o#56>tv4~Y;RM5rCN9^-Y)!b??|6=>;9wnTlK*By3Y(W3`bC% z;lf2@+tg_=S8MVK_#K6V^`SKZf=z_atr?bs>4k4nMw4Ycr|?U|z1CD^3|%yE>BlhJ z?7TljV9lvtcD(y*9z-xd^Je4OGgAfO9kLr4AIzXXcRlI4)K{-s>6Ozx#tc~AG)H#K zoA>!jN8Budc_p2FNizp`QW*I1W1I$VjN^m!u%6x|x`?I3*>oHsYd4$+$M4LwuqxeI zgJ)Uu9~18mDwX3RPmEzey(9%ga$chzS)&VU_GUx4ksc6kH>&$UXvPEM6m*nnN{7v+ z-h=18{<-Q00eV(*B}yXT&77o2H$wxB?Qwp4sfjtCJH9KT zo9WeKu*-~)cz)}yN7DRt9&6E8F;oZ?@=ld5qDl#(qG;f2)AqSoaW>VO8CdvU zZ_~h5iJGk^1FQRjHdQIgj0(`DaS`0|LbWfH)6E=)^)PKo*AU1wGK$pwYF-@AMnJNB z#R$^nN@G-e1$kcnl=5q6N=uixaB*s}f0eC*4tjnQBIrS6fmJDVV1-v~)i;e5Nu_g7 zc^ocVXXSR-VmlPJ<+j=Ca*Mk1pQKwC!(UpdcxYC8PtT!zWu7q%JO^W@d3O8p)2m=WY`t zpZGlt(GR;qFWl%w8p26tC@^5D7j&P4%U@6;p!RVZq1QEZv@z;{|Gm>12X0tgsJiOS zGIAc-fbPZY0e`ng27s0TE*HaFb+CG*O*5>Pno3c#_jY>ZyDOEM!DORLkcMBQlO$o? z0-UcKCa>DJ98WDoJ!Hx67iL*rS$cN+)odHd5E`H%98&Hp#w}^mo@^c1aHpDe+lKAy zzd$PfB9OiqSbE8n70w0Jq`e$z$sndOoiVuU+Y|jsus{J6lD!HOZIt=)!u*zBTg1ns z1I+TZ1AgXmv?4?%y#d*&r!|cb2b&Spp%-KO=p?r9NsvNXy7hZ20BJ|cR!@}0#&cL& z!CQ`e_yI-8=LPB;sC7pNh06F_%FD-IrLnoMdtb=>vA^hbl!*Cf{l zYue6gls`*)@kQnBg{5AC|KcJMYGE4t6>)niAr8SP-2wdaXM(yGNROB!?yBQ)P)`%} z_!^r-`JwiWjc(&-yJ^*OkU*wc$5CWw95Q5KR-m_%6vX7&!d*iN#Md4XnsMFdb>Y5I z5;bjhRz=|5$q=t^hs1|2{R+iPjKu`yW4(Ii2wZgG!~M~cN{zkV&5bl`N?)rkbG1=J zbGEZ{>r?=F1oR1s$7@#thL$bfKcAP+k0!vq^3J!z2ms6HnO$m*Em%JOB^qY~%nZ ztAxs!gekljF%%7t@#+r2I~9@DgQ8Nb*{8pTaZ`?tcg7GW`ssDr3|GWk49O~VdYGbA ze=GC`b60(`^W7^QjR>Qea+vsGqDF$}F1;dF-Qmrk?+q6VwTs%!2W#qAsS&)-cYrUS z7|Zmm!S(e+26Cx=9dX$Dsde*H;EQI~!$dINFskg->JgeMAACu~v~t?& z#kW^muP(@){0astC4$?dd`YJ7-J}pm!^CQuPC%ZY@&P=@z)7*W%>1yu7JYRdsCdQ`Y$7(Wm)c|v9D^-Eh|QefomDaR1V`A; zkUji1lkmy>#yx~jr!dR5AE;`UQMGYL3V$2w5kDBBm@M%Ov|c z*^4A(9n7M#PG-zZM ztiGu}>@hM?^dB!>^aoVJ!iXu$LU$@Cqbv;Qg?5zYEOC(kw>n`iA5K$+qvx{5yw5uC z9>f-o&2O;&h! zAI3vHXsLVTZ8LY=lLs(S_?3z6jX$7oH!G^v+BJ&|Ff|L7{{HuqY~H+>Hd?lnRR28d zbk!v11Evo>zrz;bVkQ6O01%u;dL%J-0eu{9EpWqaHK@8mAv4~?GVTect9>k!03py` zFf{&|eK6tO{$n`>IomPRzd41LGS$)XLNug za-`iY+SniP;TnD*Tf*G?uC${Xl6M?-p_EnTSwLhf5J}e%WQyV-trXlN=?Qw|Q% zYIjLgnsem@%)Q{*gKyXlD%b^?i+(ZnnBXdaz-bp&gU!2b_dTsM;UcW!Zf^D{TNv1( zJe0aZqK8IEyQ~G*li?e;%)T7ngMx+>bYo`f$1M>M&(8JHZGH3+yxUJy zzL9)Vxx9a)X$XFPveTuSE)JPsa!1OcYu#OKWivikw;TC-%NyR6J>PspH0yN}Z{y{0 z)4k-c`%aa|4}XRqeYlI!q}vkFDXz-#dK-diQe{$gZ3hp8gxyav`hLs!q+Rsqkf^(; zS`I)A?Z1(ex%&Y94|F11jo!qNgW-Dd0z_e0A;ZE(FKJ759+mZsCf^MLZY4AJqAq(9 zdyqtjP%WGqsDI+IB$p~@9oC^`?ENO5((Hv4#0s(;sRgCn9GjaQz`h3! z1PcIL$r|kAERZjj@(@eOad9~qPn$n4681LT;A{WRSAInKveuu(mIA*@~Wa)O^q+PGW5fnun#_%ikPjxWG`ou6Xha<0@>( z^Bb9I*NwND{LNS8oqADOE96Jppl&bWDmN_v*fobOI$}jLbHYyN-U&|`{vP+yQwO>t z3p^>0)rGwe@a`y3J6mEf3L(ECg-*IV{o5^KvM$J_wzIM*UbAoe(W|3(uq6(3tz@PM z8Yl^11O~{7%z*C*f{?vh6@JY-{Fi6Q6D}!7B>5TGt|3wOL-2dU%`AooJdlMw#VY9L zfuR^`B=5*S5u;VCDk5uFF~#i*v@qM`D>uX4I@U`qD&$IfEGOr6fFPs%Lidp40!59U z2W($YU>nny#CX= zfZ}%f?4{eeDJtO3IRa!I%@jehd0qqlU<(Tve2`!gS{89SARkgJ9e7St|GUQ>o6c6A zy=hp{JN#LG4&>`_uXWE8UmNe@tC!B*>wf>Siun<<(!mx0T-*4`9^jD;bW<-PIO*5` zlBzsVxqKzn{@T1wPti=b;G!tA^&kJ70yuwkjYy`LLZ33NoW4i(a-<}oYJCFDpzdRm zFQlK|X?|RJiKW8HI=!hMsOE(FGO2l|)xr6>HcRb1cBF-tPCpF{_${z{;hg~`%zMcs z{+Se}cvNV;UUitpVtQHF_k{~Or}zXOL;etfAyoroOQfr@dEFQ%SHX=ANeXVZdyvif z+NZ`0^Y2~)*k8rfrVi!ufHpo$#2C8jxwo4N#RRJqvgg0OrPb!+hCC+!#j4 zfK@&q8bdLyr0^HsBhEJ)7hAGP(U5HrLlfDf3b-Eta6oYt6lftkQ1PVZQX)UMi;{;a zxkYziMIrR4!Mj{O@jo`N1b1sD!;2K0)5a!(O4=Npi`)^p<0K$ z4Ts3mq*E)vh_H-#8i{KROd|#^tW?^RO>Q`p!#DT^$Zl+mAPP zfpjr2dai4%H=TA2L&V5_5k5{n0CSw4X5y0)%ri0)F3(Kmz#IbBLz&$>kKe4Ns6yqK zPA#})l;oBDq_Qs-4|Qc30?3Y+kTEt7tFjS;OJMVkyoC$b*9YK_Fb!LL&b$wLeD6Uw z=jl}ewSA>}o7!HSj7)TdY$d1X|8nu4+V%>Y_Y*Kufe9?37}*d&$67fDF@s6gvEaUl z>!HQbm1h<&cZ%@8&Gq5jGPQciyhXS=)0r#)}7)yC1k5-Zc&Hi7($ug&VXNnbR`f|SYZf6 zxylMf;!w0dQ{mEMg0T3tU$wPmx!DYl2eba=&u_nKI20A~gw_zpXpp&=*j+%y_dp-x z4}uBpST43ST$=J5m9%T>CS9ACcdX`g7WYzMspb&(_9>akF}EO9JKw>AN2>t7|VaX`h>Z zbvHQd6#|J?KQD^zb5g~L4t=0Bwrox>Sd?k{hMsTx?AUZcc@5+NfaKMyzF)zMGG72j z(g{gOY=&~_sbS~;u#YfkqiSrS23AESJ^DzQf8aIFpVFh6_xFZx4L$#wr^w-|Bz-a5 z$YepI*ygqe_v5#_={Y|W_mzrj|7bbRR21EuhT1=lFKv~(j2=B-_z7~DZy3<}n`1tu%F#vAoubOi}t9&FefK#2a39OyTY6bIyiv2uq>our9v5{?0JLx081 z_A0idVCQa!(II7sVKn9buZkLcMZX}fV{qGj(H%RlJl-hD_wmFK`+xy1_Zhn6}?8PhQHOm&w`XhE^>*qUIExg{? zJ_m89$Upv=eCR;5O!t`SXN1zbU1n20Q}6@Z8X*Y0NIoRtHNHhWtpwmFB4E=ieU6K_ z3mG@V-fq|l?L7{`rI@AN7&_o;sq>d(Oil+np}d&_EO`zq8SEt#P|Y-=Jd4IYA-}Wg zsv~z}1;CjAL#ZV=23ERU7qDBGx`$Ap>Kc45-MnjY8Tm;t!hj4Abj$?+eL)dsttZcFH8snxJVZ5ao^|7v zz^p))1(`CYBz|kcR`M46F#X!34Yho9bFCV8FUc0?7T|ZtM=7q<;HN`lzQRihW{b4F zRc4X!c4ObJ_V;u# zF|H-gFLzEGuPq5y34VUmw}7Tvy6Sf`%^Zs09R8Ws%QwyIGiI@J?(07sQ|+O&zO-jCMlTaG}lg zuHTm*JH{M>^WaQSqgFEZuESj3#xiOUhib|YacDL~-g452jMDrV?^ZRB?Rt^4l=?RG z!7IX*9qpG6=NsS7xgN9GiOnnME>502pNBmGzJsEx2Y(R636d1S+>k5Xl>8LU3G4d! zz0y2B>}lKgmU^)M*P?}9^6}imHl%KD)@$Itd;@J#-u##FIoCn)9b9yT65YlQFBm%VD)P%$`peIoXAQ``q1H;unW6hI*qu^Mzsv3|9_A7CEYm5zQHbs2 z&-i)vPZh;>q^4-r)D=`Z`D{ol;h`u6y9uz%xq$jQpxS|@?EcL{3YIvr+!t|e-H;~! z)x2xogfg*NszfEt0NT!kj%o0A7H+{_E~lL8$8pw)Zo(7VBz zpDOjrFW(P@1U|Y_+dscbS0n+ zD#wO})#DHCg$lU)NzFVay=R0;ip2z=8mm!f3~$&a!?hUAo(Cj+RzQ_aHZ+S0wNVu> z6>E{C$TZwG5L~=i6|KvZU&~tayiScI<|lWbfrFL9wcRk#%<#O5g(3DVsvcENeq}btc)>a>Vcg&b|iZ1G*8! zl(q$)?)i1=M_a*Pj=r7}tp~?zT=VjE4mzC(X*1pzg07<|pk>G-tlwC|KKCFxsU-zj z0!#g())93q-r(b_T%%uIJg)?Q4$%NOB>|YmZS364GJwPK1aym1Mah4Xg1zgD{k+nx zwyk^Aa$Z96{6Lf_@lBz+jfiMfm}!4~VO#dGK_g1XNB7^WYWs(%TTEdb`^XLzJTS9l zM&0T~3a&?Ym!B+HUk`9Pb9tp&=XYJCJ+NFCfvZEmv5+2a4koN5Ef+6NUz&B*8XgW6 zB%TEY`dR2qbf08uG*hROTV2-o{W_9iefRS;MzUrJGkbBs|B7ROc*Tq{B*IZF{tcFO z(8CdP!`_M2{flZxkGVEp9gygK`?&XQ+}8siFxv~j^9;wtasY<_rZrvSCQV>MbyFycl5X*G=R1Wsw)Am=xeCU-8>d#$^6-%mhGL0*}CoNW$l> zxfr4%=%5*t;ppza7DAfa0usMo?N1NhYB^U_|Cb{&GMY^SqCpn0pa$R{pe2Ag{%+?l z$ErRn?ko4+zj^l}8|4y~p>)lof1qNn0VrOW>U!_I8*J#gWuv;Blamq1upD_!4!B(t zI>3Zy-ADgnJQ^ZaRHv@u!a&hR9qWn{H!eL>;W%P)6tWF`HrFgg>;*-f&G!usp{jl{ z?li4lj}9tVX}!{?(O{AiDtPF?G`qT30w&# zs9}IXs+ira`9x_TjXesI&)Iyig!3qU8o{mB_$b;}l;sX=%sM2Y7`kiS3HShygpi4` zrzv5ySh@nk!fz55NytxZ#PiL$gI}n-hPR)sTdHk53M>@hCG>m+%MhqzOffO7qjZ{! zHwB+?bMVLs2eeR-puyByo^16#lp@ZQ1z2~7N-2WzjTkP!Xsy)RTD=bE+B>Nl#s^jV z%9Qy3Ihn6Ji*NJX8S=T|n=f1WQsqG&h#cQi@?j`*@@W`HjN!}|+oC8gTir-u- zS(8(Yb?BFhvAh$sdF)~f=kwX3l_0?fYA9fhl$dvG_&Jxk`)EnfcN$Z*q&Dtb5q5>= z)?TWRuyq)EIPh-9*iQf!kI`R_3Lb24cP3q*VFD;)7eB1pb%PIMoGA9svdMoKSeqJw!u zSF_^kO44;65 z{&GASzr>cHd_(!ZvOZzqcKm)Y2NjTUoyOBojcu9|v9miwo^M*NF=NN+l^NEM_Lo0K zKYtLr8co7FX*_bVQT}P>HQ&it24~iF3&CZnhW%aQR{8F&lwY~wl^5RNLQajiU7S$2 zdDJh4OHaIGdfE&^z0U9g#&Nyd6tU>lVWy7>!A>+)b00`<&K`gckyp%@4@YF)ds-6ARf2_h5G|=*0h%G8_g_9 zwYqjm`0L-!`G|Z;OA7qOX_G1b`IaQL?U7PTr!}>jfKRA7IR$qkEs9@mYDKD^uG=CL zGVn&TwF;FQ#oDTHwFZ!x6?f3Vi;HZmToeh)se|*zFa*YorRF-YSbK~NBac|kk#w8U6fSg*M1&v zHR-#Fc-GHzZC@xiniW(yhGx+e7u38OX$Uxovs;8esSi;{_B?s0cIB9qaDF?5Y)9X> zdm6lRdkIH`517SWNze^xkd~0375Krs4f{LI@5?DUOIP*yzbTw&7k7ImlLeU~%K)-L z0pfhl*BcXb=*3RTFAT9Xn6{yo?^3$`t8?r$sp#OAWJl5-bzrBMa`n%qq@RfXIoZ*seswwH+qoA8SNq~?%8pqdx><_=3P^k8 z!G7orY$IrMj)qF}JlaAjMiZ9<-mD6{^qAK+EftBj^Drxa$ywb^Igcr*bL`;=t%X)Q zm4F>T?MRR)@A~`vHK+gik8A%oX&Iydp5in;1rQqr0isVLAW1CNmi5q1YQ>s@|Ai77 z2(3a^*(X#yuhKoehCXF|4!U56JciI{Pb1)&GQ?mcX=||$N$Rjn#Q$ocO+R~z1M*AQ z2i2QarjShw{+Q=AH|0SxDx*U)4s!2k0j~kUM~dPJkKO6l@V^9&Lf^3vQfubZ*H~ ze6;+=7&G)kX>sn)C&e1nuK7}7^9uU%j#dUx_=(R19cDr(zRsPklVmeUnWw*q`~0zn zKH2a5oMztCwhP|AnM0`n%nEm;v-6uiR~TFV0F0y6Qy0a>CSz*rZyxBxUE)`>%~LqI1Ds6+N;|owlo47vH8@ z#A8zdEf>*mP%$KdAjkm|>_v8VOzK0q*K(fk&7EvbB|l$gM-7AB83#iu}u)fwb8T=5J zrg6vUM`NCW&GPfZ8Kt+AA^h99YCYWPkiAKd0CdAj0yqdsw=pvh`hz~Ihmor7zslNC z%HX00Rxjqhfl4pVT^QRID=3Yn8 z9Zqsje`M{*9AW}^aRLmXunOF1jgvrMu$w0M%;j(80Y6&tzISNCs_Fqk@>V-1z13~G z1l|ix>*I4TbtivED1V>b^eUq~i+ZNHRgss+GGU@Nc)x54Kol0|Ukw%BS^wu8LrX-yjRyPEP|d*_vSg$DACOZ}CW((B4o;G=W~KOvvOaIpbI16!fHf8l$d!CpF^ElsS_TKC(a`~K+m#Xt%}}=z^rx9u&f+}40|4QSkr-= zmtouI!6)0^h1(EX6HFx|t6xjIqOr25|vuN51fU;nix8^``;`@%;cIio{f`;B<|>)-l}Twt~7<9fkTf(hWp zpYg3}0|m#M@w7p((l)M`>G5d~@)2+g9kuAEegQz|Ar{@Ah!?(xFaSiyOCeObD*YPm zQ_mYRG;XEESWK#aCbvD6Iad8L>}kNCp{uONdT6=|pwXvBK*lj`Yi)?JZWq7m#f)g2 z3rt*6U>rO@-l=pcQn7wBNcNIyMb^_$$A}QH!6#Ulw5s#xw^y6&o%I?Q!5ufoR?w>x`h~vsXZa6~IO2Dr5m} zw+|)>RDT68VsQipxrwTX#fn4o~s^! zHjQoOl2CDS++EF+zhfbr+4Cb&t#0{^?WxP&>8YPz_s2wX87YROPR^~4b-w=KTE%4{Z;oiguXafd^>>o@6z=DtuEq!_h|5?A7v!MU6l`A_M zNmvHWZ_u8xivDtV*;vT3hY_Mv;akUHlzaT#xJl zbviJNVYXLUtw?_lrJqBCYz4u?g}(4YpXL^?{M@M|!mj|vnSv$0xaNltPR0kRET^kn zS2<)8IS>btJ-ukkWfl#aqG8RYq`fXD*=H%>$^(Y<>q; z2{I7;*krJp!G)MW9HMe1ClPiu8`BsYrI3 zN{XW%SVK;a3nwpp1un>c;j9~A=L?W67^X-to7Xpz@sRz|Q|_C7moVd|$x>mg7pF&* zNZX>i?$EK1?khM^cF`2qKvUO(6<_7_MRTV|3fp=InAX7OX#QV$Mi(@$lr}_x_Tryl z`N)le2dlF%_@VNJzHQatJ3g_MVY9sdFwcZ6gcKc6`N9JAuY*g%bpO)DjrNz>Ztbpf z7bhVJe^P4_#yuWx%E`dayip-PCiNQF`#=s?7)<=qy&>N zJ!7+m(1~tUdNdH(w?L#8P{&Ok3kGd=L?=D~l6q~GB}oz@BXI|{O40=<$^mc*#TF0- z43P}rbpyRJVk?+Vbp6mgu!xy5XL-T!`GFYjrET}+q_IU~%#S{rH}I#Wz$9T{0?I^^ zRmfI`pXs9Bj4L(F@fWDS8)lfDHaM&K%1CElAb@4Ep?vM@L-V_4U7la~%4N$l+z};@ zz+(l{yL~}8-Q#@8Afp4WUJ0j*8DI@8iEACsn4vyT{Z# zAA!+hbS-P9P)r|SfSkZ_l=UUvT)nLnIk619bt{}_<@%?VXUmTkQTNyv!9H5_(@>^( z8k=XNv}F?q*t{K>D8PEj=Ikq5T0)S6PE2eCNtrJkl)8E2nz@503t-uc z!T~&sOL!b8>vho&rk}RlS%fV+eN$@Bl)NmdL4Nr|;TBqDs3ItLANK|pd3M}NFGf1X z5fG2}y78Ce>)G1>&`k@_b{uswe5ayFBb9WkbJr6fW6;KYGAChcE{*V|o|;2a9|?Z5 z`t*g8&xgg?1L*5qH>N;%InKz${v0&MtfbMnS!j3&Fpa~kcfP>Z$bsL`gr5}H zrF=n$8d;7B9H$rqEe@(Q%%Rcbt8cNVK@OKWx~kXrp~<_2wJ~n3nG?gq;>DyWXT=ap zsk}%ZGcKn?IbRPzS6&duGQdal#^@>;XfkJof3-j1IUH87aI^5i$;rXjD|I5T=Hw)l z&t-I}F?4_jm%*i2We5xQC#j0wvAHB?fJUZo+VK$E?4LbXx4Qr?3YK{fap3S)a?u2OfCQbj+yU~(lvt;zrRU*Hd ze^jyD#-rqYCHevtBmC|~l4j@0#F7Pn%>Z0vc*!oXMLF0NY;_p#3~;UY1`9FI#OyV$ z!tDUx85`IL?n(?I`gP8t?1rV)aH(t`rXgS^7wKtiVUKPtdPN{B6ZNNNcZhN2iD_VV zY*x1E&$H(INNZ$+bs`fy<;4y8VHBdeO`d5nm7oE<-WS0-1w`50WnP}rV_kQr z3cP6vmDL`erk*=`-sq{>c>g9ow(vWL_kou_Ij*IjKc9)77}L&O>-+N{J(uA(VNG?m zkbtRuz>1l95I~s)89$$zDV+MwAL!4K{gbx+<;N|Cl&NgqPlp%joA1@{J>Cm?P_e&6 z8S2;KWY0q>mVjh~C56#D3A=7L-l-q^#$_$cj`j-k>O+IuUZk}APJ%?vib@57U}a@r zL2dxd%yqgQ!-M$%B=Zm|GDg5HT92@C@qBvinY)7rQ@lRcM~R%_sGH4leuOg&(%6rq z{GlP}!ITPuM#bg|!PKFi9y)R*=Srq-QfPMd5$~sjplqv%NF(VNDIcmHtHaT}4>S$A zp+c8SJck`a++t>Mqb|WMV__65o4=omy9cPrDKK??K2GRY+g;MCpe42e$L@YLz@Q*v z4_IRmAB&}_3#VT&!6fIaEq`uxw!8rCWSy*ouz89Y$JyVo?;-uzlxy$@U$ONM3s*Jn zlfUa)p6D!|cj3tvlGf2V6t<)7{);12LU2k8hojkon=zZjDmY()n+2$~wY9k;ertGV zS=h~jkZs*|#7a^|TlGQI;KZq4v%8@$t3{p=eG^_v6&2X5HB2J2RzMV+G1(ESARw|$ z8FFcjop4!u@9+DK-+<(%2l~^mhPn?~ErK^N#MqysBR69h2J}c8a`Ly*w6vAWQp_}J zc&DQ6#Y$G5`DpzGizy)aDrtYk5sz6hkW49}`kEXNhF;#}CefbCNJQS1t_!4|zmbQAn)oRIx{nW^~bA z+HDpR5)BGM_9%b@kho>q2Rh&erhuhMkC|t(=LU;E`HI#YyLZs9*KO|7aXYgBfXw?s z&ZA7zS*M5ftHyz!9^AJi@Kv3uMl_Ys8`X74xz*IzlyN6X;_2;cMqjy{I3IBg1WqZ& z23^RT>b+fR)nsiP9=wlxH+U-^n}wwtE7Pp0LHQ&w(AE4bThv-T)NdoWY$M0*sCmuP zVeiS{&@PJz?S_|u@?2ZcX(r5 zGZB(EDb~K(jftn1L|J$_NOL`G4CwUSV0Lag2zl2J5l!-jA4p{9uvf5kMu#Bv7Qk2r(AY*r|SoTPLSY3TwkY$o>H0M1a_z z#ejQeu=Z6?xNnTN#nQHFj@~biNH2KSmtavv?I3kc2%ePEFtms80WIKiEu3ojX4DakTTi}<2XP^#!Of9O z@xp$5qhShMi?kI7R4yLe=$7de2hHn3S?#u!A5OTLh2U_cGyNhvFP9}m^BJlDSGHM; zDQ>td4ZqJSH;b@-yqnTJ78Wsa(I@jn=yZW68uW|sg~MM~^uXR&0ikM4os#!Ps0J!D z>R2k5Z+~q&6|n1LA3J?z&$rVguXxyC)lU7~3f{JO1)LudI4AuD!w0cwq5fa4_kbs( z{v}IG?tP}Gh1>($Q{Qb9xfMnlTCy^A8SlRyAhRlGvYAKeAW9!Cn0~z!E=D&lw=RXn zoPTsKAQ+@P^*sxvrI>E}k-VcTY!^KRhsuROX@lmZlX9*hm$gxTwE#nC*GxByb%D3a zX360ubJh|10)Rn5C~TAUCZ1u^Lsg@>PIzJ4nz2xFT3!po<^4P7#q@4#yTab;kLQFi zw~Izd04)aqU#xo_<`>nwCE+d%a02_Jk@Lji*k-Am-O-ns2$v&&Ir1Y-+Yk904-M>S zq|^==nK*B4?ql*IZg!{aDYGKLzJ4XCzT^L=0fKzNN`nI&=0<2CGY>&WnL*UM=wwW% z?a4IzRKg{AFK?BPPAN|**Q1?NDrj=Zxg-UV%jxFjE-Dyvp-VvByw#6`Zc&ugLovp#e}HSlBU*#h-QUFGsv3#1b4byq^t1IXF*b z+_?1=cOJCS(ua^8hbs_qf=B2?TFTVeh^Z8QP{2PZe8gSfgsgF*juMFXV zY0WkegZrgXi3l(qRk~I{F5HV0o4DM6_Akdmp5^u9_f4zcsV(sCSM*t^P{uO!q@l;@ zrjE^1jU(T7G=6RVup#7{1Z7_OWF-^MeO#s$-Y0m|{`i|hx3X#U_n?_vfNg~C!5o4C z5Fh>evf%NxXx|k0S=~2l`G$@I;h{%VyKh{%Ap4oO0;GGeI$OuH8v4nBDRY1_=0SG@ zWL?c!Z_Q4HsY9fST3aC8^7DVJbCnWj7#(@H&i+m>cwws0N7~%3bBl+yU;Wtt*_~xK zRbmY3##CuLdLJdH45d`Ew-9tJ+Pmx`8h3w~)-590-Jm(6s;nKNHO# zj!f*gO?Gbw7t zePquSU4lbUOl1OBxg2;xjtPfX`EmSrx#0i!zB`hh$Z$b?f%00Y`TY}yq&E-QP$4M> zNMHXQF}&9EpGMompRW41W!*u3e9Uzmb*%Pww&-~v0svV5(RtMDZnk$%MEz5?? z)0hOQ`vrz^>UUibeLs)CZ%&IGiF~`D(w`mjES)p`j-t=eQI&}@TLMbj!V9`jrCYl`gmZ?KGtzeI0kF01dqn})h zO`4Dx`}}tH=u+QdY>XMCc6CYmYf$(o!ZK-M>S(s9jOyF;Y@mOUF3o}B+XIxD50PC+ zV>m7MCiZwjk733uf1Q!fytEYyIC6`ZgMnfnfik4$5kt`TkR;}T2i2@5b?CisK35N9 z`)BTSti6QHFM;VIlt@zl6U1ql?M14}xklu@HQLN`*+)CeaNgZo)ww_oF`hwDtHZHe z{?pH@?F)Yh;c>WQH31i^b6-KeGb_2SGmzc%Vp;>6NC&Q_i>IZ)cc7 zwu!Iw|1gCBr{=B!I%=h&51c0c$a?B^Q)|R7=%Fs?GP~zMZ~aMdLVW=jkB~ z2vZYFL1w6D2cGBg4z$>e>pnu=K7;nMZ;JW`pOT%enn)K{7tQ)Tm`_qO_w1dyR)05J zy6I-dv+ts}dn9U~6?t9<04PCMW)|?~yb%-K($t}ZCeU2NHLM7%kob*UZto55e0pws z3&`hqH74I5eIO_t4wOEX4A+%Qc+2r%RxoT{Y2e(Rr$i1kchLtJC#{2t7*Y7-f?w3J zwLfDs1}lk;&uN^;>IW|(bBRHy?uG}zBc<#X(5dPtc5JoZMzJF>*kmWiiU5M-V4Ya%JGeQ7Xu#o z%b{^cW?&)G;;>}q?Wg(<($TGm9JirQdq~@QR`obk7%}jdqh;m;2$ui^H8}85t?o~? z^H$Q1U+acz$*&1w^G10xl=nlq-#MG!my+ARvJ5#hOH<0KuV#nDIIA&PfbI>xc_sxJ z2+ceO%kS@&loJc)v$n_*&ABvjS=clg?jGcX(^jlbH70o9wYgJ#x8S?sbHk`^uY)%# zr4g=-d;$=7tk4F!0YwQ__BW_hr^YR|_(bh%RG+S8;Hlb%^*`cj!LkK9p)=ZpHFuvU zEtHsd^gQ5R2_|ES(kMW`!Vc(sO{?~sU36aiW5L(;EFmw=p%}J#&LUN#V*eLr0)!Lq ziJk#cSqUJ1O*r?POL_Ym$;rQE&r2+ycp`i_HEK9+xN#!Ir9PvqZMon{Ga@Q)Im~&u zu~^>jJi5^nK7Mmgjr_hj8OS`n$1ugO(`xgVhmvHRThpQwHeMcl9@My{nAON7LusV0OxB{X*I+*I&UnWSGvKRD6e|OH= zR+YTWYW7n+Dy;2fKeePynArvhU$jtqAGNfnTbsJoS0oi^ZA;OQUpJ|#uaY+^utf32 z?HFB~$R!`YW=H|tii;TptQfM#4ot|nxnw{MdZAZrPQNi@Q-*IBQ7S+D;vUJ%F zxn9J}^w%ry`DcooxBC{(6_B)ZRe-VqPbMf__7uoLqpk+w!92ujV_PsyslkI$(;Hjin)aoDCuYRj5IUox2bk+XA!N{-&+GHm>H&@zMqt!a|RlD%I z_PBu8`~OIIBB0dv$R12G;v}VrHCmCZ@jIq6T(2dols{6@u`9u1!h$pq(pda>pVSRF zCGooKPk0gJJtzvp2%zH!Ayt1lcy2Zb71+4irY&Ck-s?h&Nru}`mcYoMryqaS+x`d+QLUzYJ{0p!_@r_zYV4h}nY%)&v$|PMbLOax($w;nS(|0*MJTtL?J;o_2-k@4QBwW;y#v zS8K1|nW7c0l7T#T6h=-RuU&g}O^!?BLC~gaR-mEA9y9O^#5~o^#4JsFcq?0ieGbXxF^V8>LGl{>t+2QM{Pi5e^%hyE@lW# zS5GFV#W3XABM^V0!B7g*ksViB`Q^$syj6k*$bBJ!*JDYquLTb8CG0&dKH#f`#o^C0 z1^h+dBN2*S&88)maeYx&MutA0(Sc5C^Z3{j@9;+>BrDD^palh4i(Oo|IKb_P=VcepBl*vsDgY~~00OMd0!{nW4 z+B4ISs)-WFS53M^JyflgtEzU=?>nyPk=cU>XXh^zO5S|9I{dJ7RI$+wI`WZ8r30Iq z3pvw-qMueOWq{}_7bkYn-29g}EZOU28s%UZ0*2PgdW^w(Y0dlg zVmX*Gq(jpuXKL?j{pf!GxaUVtc%(+dTlMrk?``LJ*xCT%IkKk@d-yvAIRH(|>+X2A`d+UkR(7@njs?aIWeArT=&t{Nnbz*0;~w;S=R5t4qVKZkCf3 zK&jkS7In+b zV+Nw#qgN6!Yydp(Mw~7U3kKBL?}fOyeUemd*5P~JxMiXq`>9^9 z?2*eyZHD4TH%h+e9C*c>4)cb}jAc=F39nVk`Z!JEfidiq=U&RFyV z`SSEmLy{YEo)duoGL&1h?L-_YyUlr7K}w2kP3@7b-q3cwp^(EQf*(AF0p>xA0np;in*AA=uA>KCu|V!`famBcf_0GKDQ8c zHt~!i#PR%>M_JjA5Ivf6i}*E zDbgY$MUgID35ay*RS1M4AT^)@Dnb;bm(Yb3#r!Yj<{?729)4+6UJykPyt23**CBX zlWV)Wh|BA1#%mv)uAj;rYpwx_%@KbGMvN_liO3dy7`;*(i1F-@=c_zajAK;H0>n>& zUxYKiHbab_rhfI>=auvN5>fO5;po37xWXYRom_sTPbmJkkvEITL5gdWf3B$aB)oq% z!)Nk@@dX7G)T%g{a(3DEvv9zPj>=QikHb#Xyb}%>r((WC9e@ZA0^#mn6R%$MT4n*) z0>jvnF4 z{N8mt>xDjLQJ(p+fuw_TPBnup0GvHCwFQ-$d}c6tv|E0?){chVT)FaMehs?$q{1#& z=O)?x$JioO+C_~B$tQCh62%{gZNRaYkQc(h`*H+1k4TjuW!oR6GynHWq@Mas7nBZa_5Dgs zQ7VCjJZ!7noou|k$EMrF`}WJ`P~h-!4KfON#FG)#(yf@&Zh+0#Fgjos1QsOT@e5a5 zWZI!({(50PkCT|U;T{2=>7G}Y)D!r8sjx^Fj}Hk#Ke7}q6Oyr zz)PjDKlaqW1_&a-R{d_BF;dzY_IXJh;OqWcQCr^s%*VLFaG#_Gv)qrIh~d6yueJL) zJB>)W3QrPbZ^MZ8MhHzl9!E~y?8`h6S7)WUmhG=15nRnw%zqg;R#XOLJ_JyO5UhZl z#K^12{dR(@+lTnVwN&*AcOPGEh_zO3`OTM`XCX>oK~mx09G)saQbx&pg@*sd`VLZEYVX zAAvTzh4SZ#7XE%ieSs!gH1(1`&y)GxWXnEL(0-zdHXGM6dHJ-GW$=2wmCN$ zelUvJptbq0RCql3VbfSbCGtn(msye+|I^pC0A?Tke|Qc5AHRXgZTgiH`creNdfP^! zZBf(GCzdFb&*&VX8_@{aAFqOnVjn-Xi+?rZEX(b-4c~_Q6o03I0!vKld-zFgJ~$pQ z{OBUwUC=0M#+)A#RL83>3GPk5IF1jCl2t)2Tiwav9`hb>f_%>=a`RqFwB zcW}F**xGo6mfX=JUzBCpudX?p_#r(0cv@c6__X80PU-UhXIA&O{XR{wi+YDG^rP@&nY24jGC}^oq)Oyi5GiMLj1WYc>r)U4X$<=bSmFF zjg5J~+ld53lhueOYEZ4!{#r;e-aU07sqH>Fy2$qP*?i%dG9~#(fDIUS_t_wEjZk(<0!M)zdVWsN>1p)UxVu7WQ8E;kRntHG9(f5r z%Q&YdUzQ+Iz@$MK8`ON$MpHj{;dsrv6!WY5Lsm`Uvb$>VM;Wi1n^|$WV&Qf zTEFyrkYMZu)xNRdc1s;>Xd8aVcs8(C;f@!cP~g4Q=f02fZaN6P&g zpGED@e<+kF>2w2TQyj{=Km5-zpDe)g!z=_vA;Ob=9?E3nn~nu4TPks=-@ z^S@d&Qds*+7Q{dBJ$WE5=5V=lHwV z66cs)N77{qoH)+^67&ILX3Ps9+AfWhtxk_wzy&p?0se{j2tVfbFI=}& zkG!<6%5{%?Ephm=qe6?zOM3930j>#8n0J=ac&sR9^Jx56RgNtQ9)A$q818X?^aPuKT;^nczHE9!%A|;Yn4SdN|HdIpA+LU-$dn%pEk5gK4mqqPcG2Z zBNc!Fan?(4{lNYb*Z%Ov=K#(OCyuh+Qxkbo*@UMU@#_s;X9?>YrqPe(>n!xb-U>W=ONsa5k{!In?g*cLNb(jt z9PllAl2}qUo1gPwMdp|H5=*yF8bI4PocEWR2X{d*56j_6II;j%#I|HM&~<8=UPeYb zx5_lC_Slg$g>cIhy5|rg))j0yx<}guPKcx+C4rqs*w(h&k-8sPqEAM$Z5uzCq2<}L zvs{NHd9$4wLim}a?{EG?Aqv4fLMG;2!oZ1~3^IaG4E+?dUmg;b{Yqbmeh(t>+AZp5 z?L8!O>-$Vc?T|SzM@c0$xiX3eWXSVz>&T#+MFS?;?-a+)8f)PVJ zM`O}quhNUD*+xSem=X0&zile1{JQQDi=nk!Mc=St7-OBq-@rK4X%Ny zMyzP>^##Q?6;|urn^P~YrWp9PZwu4GrYTboaHIPGtC$)Oh)NiN3}MO6U?9K4UZg$I z>e1|PQ=RFd)wf!s85F`>iI-GphO3t#Ar`tCHh*4#Xs1h`xZLj9DIbq`_u~2%DFmoe z6(n}C{Le2kRB@l^%N6J*4oqZOAljBA-|v)=|2P?kFxQT#VtHd8!yWJN55U`k)_mfY z*@4}8^6%FZ!^Vk)uWc?(GZcUUoAA*%5C_odtOC79!*kpC_B9fMp@V0S*{^u1`nrsF zw&WN#O$#XioSGl=Shy3XF-7AogU~YmKD2Mf)nqZHTTUVJBI5>VoR*A*2%) z4ZZ|)NU+*Xdp1l&8iARC`b7+d;0x;tC()%>L;DgEk4%!^HtOlJF`BhokL4r9Z@oSa z6NxCucb`G4%ekut-et7DET!LmAv!I${8Ojmk$oz`IP~tXHH+E)`>R>EnsWAQ=V-0c zjppXcLizM>FWy-dROt)X>y}C4wE|+~wKp_`mhB#8EZ<0a>};1pT2A^my*=F~+ zugf}JPK0~Pt*H;tKM1N}|L8>TuUz!HaV5ly!uSZHPmVWqBh|b%pDc;i>2qLX}vMK8xUu2sccHwoVWP<@|*d`7|#j*H@0u{ z=%Z_}LSN)|C)@V3L&*0KBF7sXH~tOgSDz&cV*;BORf@ccS*SqgesN-q@NTzaJQ#gI zlK<-&>ceb>gHI5zlj@4KJy~AWm;4qEa@zhvHh%Z>>@2KY8t@lv4|pmUxT{k7XIyZ` zv}dj&P-2vsugr8i3#|hxnX+(ci3|9;!67djc&VK^Fi-3p@MF|;CY6Gp0qAxks0W9K zVe9nmdhhiAIOo?3cM@iLku~Y?R-LKzqH^b@ii?tGMtB54BXS9b(Sawyv9Q%2#WxyO z?Mh7r&sFC4rJa_J?DiU?$XjRV*B4aDdnUalu&c=3YcVcT3w}Q81MV&Z^NY zqJemuX@nm$m=KavXq?{lHnscWbNJb_m0;BgQZx{l(bN)L%+e{dFb^@DsuUrxM~b`_ zW)yi9{KEDN_eEthrT3Y4Ku6PD%-0`e*1INV`Ncs6ETTraq*{#khl!}lD9t(L`DGL*D^*;qtRUNt5xiuuVo$W>dtXR6CSGicSJ%|I%BSxvfu z_jTizIpJLhP+l>XEOX^uD1e~u2}$N$c;2Rk!R-k=UEXKOz1rY+>!&K{y*bCJ44@}_ z5DLQO%`9$+C**Z!8b)MSa zzxkhp5lxZFe91Kilx{*Xs#N3B?Q033`z=1Bt&@f~^D)5Xn9Yq`%{aus#Qp1Z^H^ zBFE~8nH`8_{u?;B&Q9NSfi|s&gJism4ywv6)+@C6lqAM3B*sreMZs|9gA>Jj%Je|y z0X7g?u(G%+r+m>?FQ~LPiHjs{!7Q#KfbM8HvJ+j70&)5^RqvWVlGVlP)%@`A_?HJP zIYO3&nqiu{SmN@o;@dY|pG`oO9W_X!S@Qeo*Sub-(5z5CdiE?`azgSY9)Vc^Fmdh< zK~FHF=2cr#lg{kH_1dx?=Q2WmFH76}%P!2G?d6)%boza1`y-Ie$|6h1Yc$$aa+V1AUxi|H~c zW%8CUz$GpfHXM>*Jv8j5wuq`Yv#B5fu-@d(bi<2{zijZr5AN?o{Q6@9)ao20N_a$8 zDXl!u9D%pg9C;3PnJfW?OahfQccqSCc>9B=bwkO)C6NwPtHjI<54YfB$Ba#$u3*ZV zE&nh3@Vs^JtHoK4_Cg+q&ssZPokGwn2q1RkLy6;$B)df57 zTj-&oe|wX6T=?gpE@b>HnE{|{(3D{po%%JeV5AF30Bc4ySFJll!8Q|@v5}dyLH=NM zp#0Y^g5DFOj8nxFA=crX)@Xe8`mKzLCfmwxdb5eU;Av}N_>xe>it+`k&DUl3JkOoi zVOQMj1pqq?#ARcF!uEU~UYo~4Vh}T58a+wPy9t+Et$z}r-r^G-Gu)1q0)VVyujk4cvOP>!;^|heba5j`Vf5}0pp^mevPQiGMOflxy;8T9zArMt z4i9_6iyz!wq-%;8&aoOYP1j<4vo&-q`Sq|S_2GcRV42RwUif3R$qzGcBcP~CC2$#R z4vAC5I}&b&^3I<`NN}qgmiE5hoBb4dw7!`#_&s7l5%(MQX;)KpT)IuI>aJ*ATjJ*| zg|Tv`NWtE~0}H5Hshg(Q*uJ{O+OL;w)l*l~_GSWa+gy9E-MG9QrH^%)r))pyF`hDtm~lZq&o!T3Xhi^T3CLt5ARKM6 zO8j%sJ<~t4zI`WF%A!idf!%Ltkm}Pp1O9s*Ex)vrndF)&A#MCVgLS7U(h-if`U3&uAU{2_V#1AXh z7k+NeTXv?~^`mkiO+2c2RX%q7!*dM$yjA}T9_ti>yp`eJloeb&qLp>|(D9n-r2moM z2~w0XB{Ynq{bfVTY+(y1JlFR?edX3L(CCW$PvXp=S#{g+n;S)yl2wmdHB$&Kv$(A4 zRuZC0Q;At+;CizxDZN7r5t@1j%2Z^{zY(1=Wz`#Yc+iR+FrBohxVazL>wa%&H`u5Q;V+?^>66VW#9Ik-t!u+bvN$I`RnhLAY*_x zm*8#-yz`I+s@5>nQavU8`v&)_WZV&UZYO}nt6}=%w&L0_huQL8SWrmKdT2m5kA<^k zc^BmL2rhM6Ov6`ReCoM8J4WKgCLBENU;$jkjX`}yRRsaaÒTY7w*7k*Hp2M#d> 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 K-|v~G?*9WrV0wlC literal 0 HcmV?d00001 diff --git a/docs/assets/images/2DORSTrees.jpg b/docs/assets/images/2DORSTrees.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c8ce1ccbb5605cd2ab22e58b5ea3cf5a795d6a19 GIT binary patch literal 157854 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 z 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 we want to make use of the ORS tree property to perform binary search to find our split node. See findSplit(root, low, high) in code. +=> we want to make use of the range tree property to perform binary search to find our split node. See findSplit(root, low, high) in code. 2. Left traversal & right traversal ![1DORSQuery](../../../../../../docs/assets/images/1DORSQuery.jpeg) @@ -43,7 +43,7 @@ Querying: O(k + logn) ### Dynamic Updates If we need to dynamically update the tree, insertion and deletion is done in a manner similar to AVL trees (insert/delete and rotate to maintain height balance), except now we need to ensure that we are adding the new node -as a leaf node, and we still need to adhere to the ORS tree property. +as a leaf node, and we still need to adhere to the range tree property. Note how the ORS tree property enables efficient dynamic updating of the tree, as the value of the nodes do not need to change after rotation. diff --git a/src/main/java/algorithms/orthogonalRangeSearching/twoDim/OrthogonalRangeSearching.java b/src/main/java/algorithms/orthogonalRangeSearching/twoDim/OrthogonalRangeSearching.java index 8a60ea6a..407bf6e4 100644 --- a/src/main/java/algorithms/orthogonalRangeSearching/twoDim/OrthogonalRangeSearching.java +++ b/src/main/java/algorithms/orthogonalRangeSearching/twoDim/OrthogonalRangeSearching.java @@ -301,7 +301,7 @@ public static void YSearch(RangeTreeNode v, int yLow, int yHigh, Arra public static List search(RangeTreeNode tree, int xLow, int xHigh, int yLow, int yHigh) { RangeTreeNode splitNodeX = findXSplit(tree, xLow, xHigh); ArrayList result = new ArrayList<>(); - if (splitNodeX != null) { //will split node ever be leaf.... possible if range is size 1 + if (splitNodeX != null) { if (splitNodeX.getLeft() == null && splitNodeX.getRight() == null && splitNodeX.getVal()[0] >= xLow && splitNodeX.getVal()[0] <= xHigh) { // if split node is leaf YSearch(splitNodeX, yLow, yHigh, result); diff --git a/src/main/java/algorithms/orthogonalRangeSearching/twoDim/README.md b/src/main/java/algorithms/orthogonalRangeSearching/twoDim/README.md new file mode 100644 index 00000000..4d12debd --- /dev/null +++ b/src/main/java/algorithms/orthogonalRangeSearching/twoDim/README.md @@ -0,0 +1,68 @@ +# 2D Orthogonal Range Searching + +2D orthogonal range searching is a computational problem that involves efficiently answering queries about points +in a two-dimensional space that fall within a specified axis-aligned rectangular range (orthogonal range). In other +words, given a set of points in 2D, find me all the points that lie within a specific rectangle. + +To do so, we can extend the idea of 1D range trees to the 2D context. + +Strategy +- Each node in the x-tree has a set of points in its subtree +- Store a y-tree at each x-node containing all the points in the x-subtree + +![2DORS](../../../../../../docs/assets/images/2DORS.jpg) + +1. Build an x-tree using only x-coordinates. + - This should be done in the exact same way as you would for a 1D range tree. +2. For every node in the x-tree, build a y-tree out of nodes in the x-subtree using only y-coordinates. + +![2DORSTrees](../../../../../../docs/assets/images/2DORSTrees.jpg) + +Given the 2D range tree, we now want to query the points in a given rectangle +i.e. search(tree, xLow, xHigh, yLow, yHigh). + +We first want to find the points that will satisfy the x-condition i.e. find me all points whose x-coordinates are +between xLow and xHigh. To do so, we first need to find our split node in the x-tree, by performing binary search while +traversing the x-tree - similar to how we found the split node in a 1D range tree. This will give us our X-split. + +Now given our X-split, we want to find points that satisfy both our x-condition and y-condition. + +Let's first explore our x-left subtree (X-left traversal). If (xLow <= x-coordinate of curr node), we are confident +that the entire right subtree of the curr node satisfies our x-condition (because of BST property). + +Now we want to perform a Y-search to find the points that also satisfy the y-condition. To do so, we first need to +find our split node in the y-tree i.e. Y-split. Notice that the problem is now reduced to a 1D ORS problem. Once we +have found Y-split, we can simply perform left traversal and right traversal from Y-split, similar to how it is done +in 1D ORS. + +A similar symmetric logic applies in exploring our x-right subtree. + +![2DORSQuery](../../../../../../docs/assets/images/2DORSQuery.jpg) +Image Source: https://www.cse.wustl.edu/~taoju/cse546/lectures/Lecture21_rangequery_2d.pdf + +## Complexity Analysis +**Time**: + +Build Tree (cost incurred once only): O(nlogn) limited by sorting step + +Querying: O(k + log^2n) +- O(logn) to find X-split +- O(logn) recursing steps in X-left traversal/X-right-traversal +- O(logn) y-tree searches of cost O(logn) => overall: O(log^2n) +- O(k) enumerating output + +**Space**: O(nlogn) +- Each point appears in at most 1 y-tree per level. (Refer to 1st image for visualisation) +- There are O(logn) levels in the x-tree. +- Therefore, each node appears in at most O(logn) y-trees. => overall: O(nlogn) +- The x-tree takes O(n) space. + +## Notes +### Dynamic Updates +Unlike 1D range trees, dynamic updates in a 2D range tree are inefficient as rotations in the x-tree might involve +entirely rebuilding the y-trees for the rotated notes. Therefore, 2D ORS is mainly used for static querying. + +### d-dimensional Range Trees +- Query cost: O(k + log^dn) +- Build tree cost: O(nlog^(d-1)n) +- Space: O(nlog^(d-1)n) \ No newline at end of file From 9e00f174cbaf0286651ac03cf2bd88d31d2bcdcb Mon Sep 17 00:00:00 2001 From: kaitinghh <114789615+kaitinghh@users.noreply.github.com> Date: Sat, 23 Dec 2023 23:02:34 +0800 Subject: [PATCH 08/51] fixed typo --- .../java/algorithms/orthogonalRangeSearching/twoDim/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/algorithms/orthogonalRangeSearching/twoDim/README.md b/src/main/java/algorithms/orthogonalRangeSearching/twoDim/README.md index 4d12debd..f2c2b70b 100644 --- a/src/main/java/algorithms/orthogonalRangeSearching/twoDim/README.md +++ b/src/main/java/algorithms/orthogonalRangeSearching/twoDim/README.md @@ -43,7 +43,7 @@ Image Source: https://www.cse.wustl.edu/~taoju/cse546/lectures/Lecture21_rangequ ## Complexity Analysis **Time**: -Build Tree (cost incurred once only): O(nlogn) limited by sorting step +Build Tree (cost incurred once only): O(nlog^2n) Querying: O(k + log^2n) - O(logn) to find X-split From 25301d4dd4e1621012c3e07c892b9ccbd2408752 Mon Sep 17 00:00:00 2001 From: kaitinghh <114789615+kaitinghh@users.noreply.github.com> Date: Mon, 11 Mar 2024 22:50:58 +0800 Subject: [PATCH 09/51] refactor: edit 1D ORS following comments --- .../oneDim/OrthogonalRangeSearching.java | 61 ++++++++++--------- .../orthogonalRangeSearching/oneDim/README.md | 21 ++++--- 2 files changed, 45 insertions(+), 37 deletions(-) diff --git a/src/main/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearching.java b/src/main/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearching.java index b88e0d7f..489f0b31 100644 --- a/src/main/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearching.java +++ b/src/main/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearching.java @@ -22,17 +22,11 @@ public static RangeTreeNode buildTree(int[] inputs, int start, int end) if (start > end) { return null; - } else if (end - start + 1 > 3) { + } else if (start == end) { + return new RangeTreeNode<>(inputs[start]); + } else { return new RangeTreeNode<>(inputs[mid], buildTree(inputs, start, mid), buildTree(inputs, mid + 1, end)); - } else if (end - start + 1 == 3) { - return new RangeTreeNode<>(inputs[mid], buildTree(inputs, start, mid), - buildTree(inputs, end, end)); - } else if (end - start + 1 == 2) { - return new RangeTreeNode<>(inputs[mid], buildTree(inputs, start, start), - buildTree(inputs, end, end)); - } else { - return new RangeTreeNode<>(inputs[mid]); } } @@ -52,7 +46,7 @@ public static RangeTreeNode findSplit(RangeTreeNode root, int return null; } else { if (high <= v.getVal()) { - if (v.getLeft() == null && v.getRight() == null) { // reached the leaf + if (isLeaf(v)) { break; } v = v.getLeft(); @@ -77,7 +71,7 @@ public static void allLeafTraversal(RangeTreeNode v, List resu if (v.getLeft() != null) { allLeafTraversal(v.getLeft(), result); } - if (v.getLeft() == null && v.getRight() == null) { // leaf + if (isLeaf(v)) { result.add(v.getVal()); } if (v.getRight() != null) { @@ -95,7 +89,7 @@ public static void allLeafTraversal(RangeTreeNode v, List resu */ public static void leftTraversal(RangeTreeNode v, int low, List result) { if (v != null) { - if (v.getLeft() == null && v.getRight() == null) { // leaf + if (isLeaf(v)) { result.add(v.getVal()); } else { if (low <= v.getVal()) { @@ -117,7 +111,7 @@ public static void leftTraversal(RangeTreeNode v, int low, List v, int high, List result) { if (v != null) { - if (v.getLeft() == null && v.getRight() == null && v.getVal() <= high) { // leaf, need extra check + if (isLeaf(v) && v.getVal() <= high) { // leaf, need extra check result.add(v.getVal()); } else { if (high > v.getVal()) { @@ -142,8 +136,8 @@ public static Object[] search(RangeTreeNode tree, int low, int high) { RangeTreeNode splitNode = OrthogonalRangeSearching.findSplit(tree, low, high); ArrayList result = new ArrayList<>(); if (splitNode != null) { - if (splitNode.getLeft() == null && splitNode.getRight() == null - && splitNode.getVal() >= low && splitNode.getVal() <= high) { // if split node is leaf + if (isLeaf(splitNode) && splitNode.getVal() >= low + && splitNode.getVal() <= high) { result.add(splitNode.getVal()); } leftTraversal(splitNode.getLeft(), low, result); @@ -152,7 +146,11 @@ public static Object[] search(RangeTreeNode tree, int low, int high) { return result.toArray(); } - // Functions from here onwards are designed to support dynamic updates. + private static boolean isLeaf(RangeTreeNode node) { + return node.getLeft() == null && node.getRight() == null; + } + + // FUNCTIONS FROM HERE ONWARDS ARE DESIGNED TO SUPPORT DYNAMIC UPDATES. /** * Configures the height and parent nodes for the nodes in the Range Tree. @@ -276,7 +274,7 @@ private static RangeTreeNode rotateRight(RangeTreeNode n) { * @return new root after rotation */ private static RangeTreeNode rotateLeft(RangeTreeNode n) { - RangeTreeNode newRoot = n.getRight(); + RangeTreeNode newRoot = n.getRight(); // newRoot is the right subtree of the original root RangeTreeNode newRightSub = newRoot.getLeft(); newRoot.setLeft(n); n.setRight(newRightSub); @@ -299,12 +297,14 @@ private static RangeTreeNode rebalance(RangeTreeNode n) { updateHeight(n); int balance = getBalance(n); if (balance < -1) { // right-heavy case - if (height(n.getRight().getLeft()) > height(n.getRight().getRight())) { + RangeTreeNode rightChild = n.getRight(); + if (height(rightChild.getLeft()) > height(rightChild.getRight())) { n.setRight(rotateRight(n.getRight())); } n = rotateLeft(n); } else if (balance > 1) { // left-heavy case - if (height(n.getLeft().getRight()) > height(n.getLeft().getLeft())) { + RangeTreeNode leftChild = n.getLeft(); + if (height(leftChild.getRight()) > height(leftChild.getLeft())) { n.setLeft(rotateLeft(n.getLeft())); } n = rotateRight(n); @@ -320,26 +320,29 @@ private static RangeTreeNode rebalance(RangeTreeNode n) { * @return The root node of the updated Range Tree. */ public static RangeTreeNode delete(RangeTreeNode node, int val) { - if (node.getLeft().getLeft() == null && node.getLeft().getRight() == null - && val == node.getLeft().getVal()) { // left node is the leaf node - node.setVal(node.getRight().getVal()); + RangeTreeNode leftChild = node.getLeft(); + RangeTreeNode rightChild = node.getRight(); + + if (leftChild.getLeft() == null && leftChild.getRight() == null + && val == leftChild.getVal()) { // left node is the leaf node + node.setVal(rightChild.getVal()); node.setLeft(null); node.setRight(null); - } else if (node.getRight().getLeft() == null && node.getRight().getRight() == null - && val == node.getRight().getVal()) { // right node is the leaf node + } else if (rightChild.getLeft() == null && rightChild.getRight() == null + && val == rightChild.getVal()) { // right node is the leaf node node.setLeft(null); node.setRight(null); } else { if (val <= node.getVal()) { - if (node.getLeft() != null) { - node.setLeft(delete(node.getLeft(), val)); + if (leftChild != null) { + node.setLeft(delete(leftChild, val)); } if (val == node.getVal()) { // duplicate node - node.setVal(getMostRight(node.getLeft()).getVal()); // update the duplicate key + node.setVal(getMostRight(leftChild).getVal()); // update the duplicate key } } else { - if (node.getRight() != null) { - node.setRight(delete(node.getRight(), val)); + if (rightChild != null) { + node.setRight(delete(rightChild, val)); } } } diff --git a/src/main/java/algorithms/orthogonalRangeSearching/oneDim/README.md b/src/main/java/algorithms/orthogonalRangeSearching/oneDim/README.md index 7709bdff..5df29c01 100644 --- a/src/main/java/algorithms/orthogonalRangeSearching/oneDim/README.md +++ b/src/main/java/algorithms/orthogonalRangeSearching/oneDim/README.md @@ -1,14 +1,15 @@ # 1D Orthogonal Range Searching 1D orthogonal range searching is a computational problem where you search for elements or data points within a -specified 1D range (interval) in a collection of 1D data (e.g. Find me everyone between ages 22 and 27). +specified 1D range (interval) in a collection of 1D data (e.g. Find me everyone between ages 22 and 27). Additionally, +we also want to support efficient insertions of new data points into the maintained set. -While we can simply sort (and binary search the low and high of the specified range) to return all data points within -the specified range, each query will minimally take O(nlogn) due to the sorting step, assuming dynamic updating of -the data. +One strategy is would be to sort all the data points in O(nlogn) time, then insertion would take O(n). We can binary +search the low and high of the specified range to return all data points within in O(logn) time. This would be a +reasonable approach if the no. of queries >> no. of insertions. -The goal of 1D Orthogonal Range Searching is to efficiently identify and retrieve all data points that fall within the -given range. +In cases where the no. of insertions >> no. of queries, we might want to further optimise the time complexity of +insertions to O(logn) using a 1D range tree. Strategy: 1. Use a binary search tree @@ -20,7 +21,9 @@ Strategy: Say we want to find all the nodes between 10 and 50 i.e. query(10, 50). We would want to: 1. Find split node: highest node where search includes both left & right subtrees => we want to make use of the range tree property to perform binary search to find our split node. See findSplit(root, low, high) in code. -2. Left traversal & right traversal +2. Left traversal & right traversal +- Left traversal covers the range within [low, splitNode] +- Right traversal covers the range within (splitNode, high] ![1DORSQuery](../../../../../../docs/assets/images/1DORSQuery.jpeg) Image Source: Lecture Slides @@ -28,7 +31,9 @@ Image Source: Lecture Slides ## Complexity Analysis **Time**: -Build Tree (cost incurred once only): O(nlogn) limited by sorting step +Build Tree (cost incurred once only): +- if given an unsorted array, O(nlogn) limited by sorting step +- if given a sorted array, O(n) Querying: O(k + logn) - Find Split Node: O(logn) (binary search) From b4ddf1ea681f540872f23ad160a393c26924587f Mon Sep 17 00:00:00 2001 From: kaitinghh <114789615+kaitinghh@users.noreply.github.com> Date: Mon, 11 Mar 2024 23:32:53 +0800 Subject: [PATCH 10/51] refactor: edit 2D ORS following comments --- .../twoDim/OrthogonalRangeSearching.java | 70 ++++++++----------- .../orthogonalRangeSearching/twoDim/README.md | 9 ++- 2 files changed, 34 insertions(+), 45 deletions(-) diff --git a/src/main/java/algorithms/orthogonalRangeSearching/twoDim/OrthogonalRangeSearching.java b/src/main/java/algorithms/orthogonalRangeSearching/twoDim/OrthogonalRangeSearching.java index 407bf6e4..c92e3e8c 100644 --- a/src/main/java/algorithms/orthogonalRangeSearching/twoDim/OrthogonalRangeSearching.java +++ b/src/main/java/algorithms/orthogonalRangeSearching/twoDim/OrthogonalRangeSearching.java @@ -24,24 +24,13 @@ public static RangeTreeNode buildXTree(List inputs, int st if (start > end) { return null; - } else if (end - start + 1 > 3) { - RangeTreeNode node = new RangeTreeNode<>(inputs.get(mid), buildXTree(inputs, start, mid), - buildXTree(inputs, mid + 1, end)); - node.setYTree(buildYTree(inputs, start, end)); - return node; - } else if (end - start + 1 == 3) { - RangeTreeNode node = new RangeTreeNode<>(inputs.get(mid), buildXTree(inputs, start, mid), - buildXTree(inputs, end, end)); - node.setYTree(buildYTree(inputs, start, end)); - return node; - } else if (end - start + 1 == 2) { - RangeTreeNode node = new RangeTreeNode<>(inputs.get(mid), - buildXTree(inputs, start, start), - buildXTree(inputs, end, end)); + } else if (start == end) { + RangeTreeNode node = new RangeTreeNode<>(inputs.get(mid)); node.setYTree(buildYTree(inputs, start, end)); return node; } else { - RangeTreeNode node = new RangeTreeNode<>(inputs.get(mid)); + RangeTreeNode node = new RangeTreeNode<>(inputs.get(mid), buildXTree(inputs, start, mid), + buildXTree(inputs, mid + 1, end)); node.setYTree(buildYTree(inputs, start, end)); return node; } @@ -58,7 +47,6 @@ public static RangeTreeNode buildXTree(List inputs, int st */ private static RangeTreeNode buildYTree(List inputs, int start, int end) { - int mid = (end + start) / 2; List ySortedSublist = inputs.subList(start, end + 1); ySortedSublist.sort(Comparator.comparingInt(a -> a[1])); //sort by y-coordinate @@ -80,17 +68,11 @@ private static RangeTreeNode buildYTreeHelper(List inputs, if (start > end) { return null; - } else if (end - start + 1 > 3) { + } else if (start == end) { + return new RangeTreeNode<>(inputs.get(start)); + } else { return new RangeTreeNode<>(inputs.get(mid), buildYTree(inputs, start, mid), buildYTree(inputs, mid + 1, end)); - } else if (end - start + 1 == 3) { - return new RangeTreeNode<>(inputs.get(mid), buildYTree(inputs, start, mid), - buildYTree(inputs, end, end)); - } else if (end - start + 1 == 2) { - return new RangeTreeNode<>(inputs.get(mid), buildYTree(inputs, start, start), - buildYTree(inputs, end, end)); - } else { - return new RangeTreeNode<>(inputs.get(mid)); } } @@ -133,7 +115,7 @@ public static RangeTreeNode findXSplit(RangeTreeNode root, public static void XLeftTraversal(RangeTreeNode v, int xLow, int xHigh, int yLow, int yHigh, ArrayList result) { if (v != null) { - if (v.getLeft() == null && v.getRight() == null && v.getVal()[0] >= xLow && v.getVal()[0] <= xHigh) { //leaf + if (isLeaf(v) && v.getVal()[0] >= xLow && v.getVal()[0] <= xHigh) { //leaf YSearch(v, yLow, yHigh, result); } else { if (xLow <= v.getVal()[0]) { @@ -158,7 +140,7 @@ public static void XLeftTraversal(RangeTreeNode v, int xLow, int xHig public static void XRightTraversal(RangeTreeNode v, int xLow, int xHigh, int yLow, int yHigh, ArrayList result) { if (v != null) { - if (v.getLeft() == null && v.getRight() == null && v.getVal()[0] >= xLow && v.getVal()[0] <= xHigh) { //leaf + if (isLeaf(v) && v.getVal()[0] >= xLow && v.getVal()[0] <= xHigh) { //leaf YSearch(v, yLow, yHigh, result); } else { if (xHigh >= v.getVal()[0]) { @@ -186,7 +168,7 @@ public static RangeTreeNode findYSplit(RangeTreeNode root, return null; } else { if (yHigh <= v.getVal()[1]) { - if (v.getLeft() == null && v.getRight() == null) { // extra check since ysplit might be leaf node + if (isLeaf(v)) { // extra check since ysplit might be leaf node break; } else { v = v.getLeft(); @@ -212,7 +194,7 @@ public static void allLeafTraversal(RangeTreeNode v, List if (v.getLeft() != null) { allLeafTraversal(v.getLeft(), result); } - if (v.getLeft() == null && v.getRight() == null) { // leaf + if (isLeaf(v)) { result.add(v.getVal()); } if (v.getRight() != null) { @@ -228,16 +210,16 @@ public static void allLeafTraversal(RangeTreeNode v, List * @param low The lower bound of the Y-coordinate range. * @param result A list to store the results. */ - public static void leftTraversal(RangeTreeNode v, int low, List result) { + public static void YLeftTraversal(RangeTreeNode v, int low, List result) { if (v != null) { - if (v.getLeft() == null && v.getRight() == null) { // leaf + if (isLeaf(v)) { result.add(v.getVal()); } else { if (low <= v.getVal()[1]) { - leftTraversal(v.getLeft(), low, result); + YLeftTraversal(v.getLeft(), low, result); allLeafTraversal(v.getRight(), result); } else { // definitely a qualifying leaf has to exist - leftTraversal(v.getRight(), low, result); + YLeftTraversal(v.getRight(), low, result); } } } @@ -250,16 +232,16 @@ public static void leftTraversal(RangeTreeNode v, int low, List v, int high, List result) { + public static void YRightTraversal(RangeTreeNode v, int high, List result) { if (v != null) { - if (v.getLeft() == null && v.getRight() == null && v.getVal()[1] <= high) { // leaf, need extra check + if (isLeaf(v) && v.getVal()[1] <= high) { // leaf, need extra check result.add(v.getVal()); } else { if (high > v.getVal()[1]) { allLeafTraversal(v.getLeft(), result); - rightTraversal(v.getRight(), high, result); + YRightTraversal(v.getRight(), high, result); } else { // a qualifying leaf might or might not exist, we are just exploring - rightTraversal(v.getLeft(), high, result); + YRightTraversal(v.getLeft(), high, result); } } } @@ -275,15 +257,14 @@ public static void rightTraversal(RangeTreeNode v, int high, List v, int yLow, int yHigh, ArrayList result) { if (v != null) { - System.out.println(v.getVal()[0]); RangeTreeNode splitNodeY = findYSplit(v.getYTree(), yLow, yHigh); if (splitNodeY != null) { - if (splitNodeY.getLeft() == null && splitNodeY.getRight() == null + if (isLeaf(splitNodeY) && splitNodeY.getVal()[1] >= yLow && splitNodeY.getVal()[1] <= yHigh) { // if split node is leaf result.add(splitNodeY.getVal()); } - leftTraversal(splitNodeY.getLeft(), yLow, result); - rightTraversal(splitNodeY.getRight(), yHigh, result); + YLeftTraversal(splitNodeY.getLeft(), yLow, result); + YRightTraversal(splitNodeY.getRight(), yHigh, result); } } } @@ -302,7 +283,7 @@ public static List search(RangeTreeNode tree, int xLow, in RangeTreeNode splitNodeX = findXSplit(tree, xLow, xHigh); ArrayList result = new ArrayList<>(); if (splitNodeX != null) { - if (splitNodeX.getLeft() == null && splitNodeX.getRight() == null + if (isLeaf(splitNodeX) && splitNodeX.getVal()[0] >= xLow && splitNodeX.getVal()[0] <= xHigh) { // if split node is leaf YSearch(splitNodeX, yLow, yHigh, result); } @@ -311,4 +292,9 @@ public static List search(RangeTreeNode tree, int xLow, in } return result; } + + private static boolean isLeaf(RangeTreeNode node) { + return node.getLeft() == null && node.getRight() == null; + } + } diff --git a/src/main/java/algorithms/orthogonalRangeSearching/twoDim/README.md b/src/main/java/algorithms/orthogonalRangeSearching/twoDim/README.md index f2c2b70b..73c436b2 100644 --- a/src/main/java/algorithms/orthogonalRangeSearching/twoDim/README.md +++ b/src/main/java/algorithms/orthogonalRangeSearching/twoDim/README.md @@ -22,8 +22,8 @@ Given the 2D range tree, we now want to query the points in a given rectangle i.e. search(tree, xLow, xHigh, yLow, yHigh). We first want to find the points that will satisfy the x-condition i.e. find me all points whose x-coordinates are -between xLow and xHigh. To do so, we first need to find our split node in the x-tree, by performing binary search while -traversing the x-tree - similar to how we found the split node in a 1D range tree. This will give us our X-split. +between xLow and xHigh. To do so, we first need to find our split node in the x-tree, by performing binary search[^1] +while traversing the x-tree - similar to how we found the split node in a 1D range tree. This will give us our X-split. Now given our X-split, we want to find points that satisfy both our x-condition and y-condition. @@ -65,4 +65,7 @@ entirely rebuilding the y-trees for the rotated notes. Therefore, 2D ORS is main ### d-dimensional Range Trees - Query cost: O(k + log^dn) - Build tree cost: O(nlog^(d-1)n) -- Space: O(nlog^(d-1)n) \ No newline at end of file +- Space: O(nlog^(d-1)n) + +[^1] This reference to binary search differs from our typical binary search formulation, but essentially refers +to the findSplit function where you walk down the balanced tree and remove roughly half of the nodes each time. \ No newline at end of file From 49057090b4d85589838bdd0a21a4637c6583d9cc Mon Sep 17 00:00:00 2001 From: junneng Date: Sun, 31 Dec 2023 21:31:19 +0800 Subject: [PATCH 11/51] Add Prim's algorithm --- .../minimumSpanningTree/prims/Edge.java | 24 ++ .../minimumSpanningTree/prims/Node.java | 64 +++++ .../minimumSpanningTree/prims/Pair.java | 38 --- .../minimumSpanningTree/prims/Prim.java | 245 +++++++++++------- 4 files changed, 235 insertions(+), 136 deletions(-) create mode 100644 src/main/java/algorithms/minimumSpanningTree/prims/Edge.java create mode 100644 src/main/java/algorithms/minimumSpanningTree/prims/Node.java delete mode 100644 src/main/java/algorithms/minimumSpanningTree/prims/Pair.java diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Edge.java b/src/main/java/algorithms/minimumSpanningTree/prims/Edge.java new file mode 100644 index 00000000..0ca05f86 --- /dev/null +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Edge.java @@ -0,0 +1,24 @@ +package algorithms.minimumSpanningTree.prims; + +/** + * Helper class to encapsulate information about an edge; + * specifically, tells us the weight of an edge and the node on the other end + * (assumes that the starting node of the edge is known) + */ +public class Edge { + private final int weight; + private final Node endNode; + + public Edge(int weight, Node endNode) { + this.weight = weight; + this.endNode = endNode; + } + + public Node getEndNode() { + return this.endNode; + } + + public int getWeight() { + return this.weight; + } +} \ No newline at end of file diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java new file mode 100644 index 00000000..8f0d33d6 --- /dev/null +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java @@ -0,0 +1,64 @@ +package algorithms.minimumSpanningTree.prims; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * Helper class to encapsulate information about a node; + * specifically, tells us the weight of an edge and the node on the other end + * (assumes that the starting node of the edge is known) + */ +public class Node { + private final List edges; + private boolean isVisited = false; + private int currMinDistance; + + public Node(List edges) { + this.edges = new ArrayList<>(edges); + } + public Node() { + this.edges = new ArrayList<>(); + } + + public List getEdges() { + return this.edges; + } + + public int getCurrMinDistance() { + return currMinDistance; + } + + public void setVisited(boolean isVisited) { + this.isVisited = isVisited; + } + + public boolean isVisited() { + return this.isVisited; + } + + public void setCurrMinDistance(int currMinDistance) { + this.currMinDistance = currMinDistance; + } + + public String toString() { + return this.edges.toString(); + } + + public void addEdge(Edge mstEdge) { + this.edges.add(mstEdge); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Node node = (Node) o; + return isVisited == node.isVisited && edges.equals(node.edges); + } + + @Override + public int hashCode() { + return Objects.hash(edges, isVisited); + } +} diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Pair.java b/src/main/java/algorithms/minimumSpanningTree/prims/Pair.java deleted file mode 100644 index 0d6cc805..00000000 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Pair.java +++ /dev/null @@ -1,38 +0,0 @@ -package algorithms.minimumSpanningTree.prims; - -/** - * Helper class to encapsulate information about an edge; - * specifically, tells us the weight of an edge and the node on the other end - * (assumes that the starting node of the edge is known) - */ -public class Pair { - private int dist; - private int endNode; - - /** - * Constructs an instance of a pair, that represents an edge. - * - * @param dist the distance encapsulated. - * @param endNode the node at the end of the edge. - */ - public Pair(int dist, int endNode) { - this.dist = dist; - this.endNode = endNode; - } - - public int getDist() { - return dist; - } - - public void setDist(int dist) { - this.dist = dist; - } - - public int getEndNode() { - return endNode; - } - - public void setEndNode(int endNode) { - this.endNode = endNode; - } -} diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java index f2c49504..b79182ed 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java @@ -1,115 +1,164 @@ package algorithms.minimumSpanningTree.prims; -import java.util.Comparator; -import java.util.HashSet; -import java.util.PriorityQueue; -import java.util.Set; +import java.util.*; -/** +/** * Implementation of Prim's Algorithm to find MSTs - * Idea: - * Starting from any source (this will be the first node to be in the MST), - * pick the lightest outgoing edge, and include the node at the other end as part of MST - * Now repeatedly do the above by picking the lightest outgoing edge adjacent to any node in the MST - * (ensuring the other end of the node is not already in the MST) - * Do until the MST has all the nodes. - *

+ * Idea: + * Starting from any source (this will be the first node to be in the MST), + * pick the lightest outgoing edge, and include the node at the other end as part of a set of nodes S. + * Now repeatedly do the above by picking the lightest outgoing edge adjacent to any node in S. + * (ensuring the other end of the node is not already in the MST) + * Repeat until S contains all nodes in the graph. S is the MST. + * * Motivating Example: Minimum Cost to Connect All Points - *

- * A -9- C -2- E - * / / \ \ - * 3 4 7 2 - * / / \ / - * F -1- B --5-- D - *

+ * + A -9- C -2- E + / / \ \ + 3 4 7 2 + / / \ / + F -1- B --5-- D +*/ + +/** * Implementation 1: Using heap - * Time: O(V) + O(ElogE) (since heap could possibly hold E number of weights) + O(E-V) (nodes that have been 'seen' - * are still added to the heap, just not expanded) + O(V^2) - * Space: O(V) (hashmap to decide on MST) + O(E) (heap) = O(V+E) = O(E) + * Time: O(V) + O(ElogV) (since heap could possibly hold E number of weights) + O(E-V) (nodes that have been 'seen' are still added to the heap, just not expanded) + O(V^2) + * Space: O(V) (hashmap to decide on MST) + O(E) (heap) = O(V+E) = O(E) */ + public class Prim { - /** - * points: Adjacency matrix that encapsulates the distance/weight between nodes - * adjM[i][j] is the weight of the edge connecting points i and j; a value of 0 suggests there is no connection - * between i and j - * - * @param adjM Adjacency matrix that encapsulates the distance/weight between nodes - * @return minimum weight of the spanning tree - */ - public int minCostConnectPoints(int[][] adjM) { - int v = adjM.length; - int minCost = 0; - Set mst = new HashSet<>(); - mst.add(0); - PriorityQueue pq = new PriorityQueue<>(Comparator.comparingInt(Pair::getDist)); - for (int i = 0; i < v; i++) { - if (!mst.contains(i)) { - if (adjM[0][i] != 0) { // ensure valid edge - pq.add(new Pair(adjM[0][i], i)); - } - } +// /** +// * points: Adjacency matrix that encapsulates the distance/weight between nodes +// * adjM[i][j] is the weight of the edge connecting points i and j; a value of 0 suggests there is no connection between i and j +// * @param adjM Adjacency matrix that encapsulates the distance/weight between nodes +// * @return minimum weight of the spanning tree +// */ +// public int minCostConnectPoints(int[][] adjM) { +// int v = adjM.length; +// int minCost = 0; +// Set mst = new HashSet<>(); +// mst.add(0); +// PriorityQueue pq = new PriorityQueue<>( +// (a, b) -> a.dist - b.dist +// ); +// for (int i = 0; i < v; i++) { +// if (!mst.contains(i)) { +// if (adjM[0][i] != 0) { // ensure valid edge +// pq.add(new Edge(adjM[0][i], i)); +// } +// } +// } +// while (mst.size() != v) { +// Edge popped = pq.poll(); +// if (mst.contains(popped.endNode)) { +// continue; +// } +// minCost += popped.dist; +// mst.add(popped.endNode); +// for (int i = 0; i < v; i++) { +// if (mst.contains(i)) { +// continue; +// } +// if (adjM[popped.endNode][i] != 0) { // ensure valid edge +// pq.add(new Edge(adjM[popped.endNode][i], i)); +// } +// } +// } +// return minCost; +// } +// +// /** +// * Alternative implementation that simply uses array to hold weights rather than heap. +// * Note: Starts from the node labelled 0 and repeatedly update +// * which stores the minimum weight from any node in the MST to other nodes. +// * Time: O(V) + O(V*2V) +// * Space: O(V) +// * @param adjM Adjacency matrix that encapsulates the distance/weight between nodes +// * @return minimum weight of the spanning tree +// */ +// public int minCostConnectPoints2(int[][] adjM) { +// int v = adjM.length; +// int[] weights = new int[v]; +// +// for (int i = 0; i < v; i++) { +// weights[i] = adjM[0][i]; +// } +// +// Set mst = new HashSet<>(); +// mst.add(0); // start from source 0 +// int ans = 0; +// while (mst.size() < v) { +// int next = v; +// for (int i = 0; i < v; i++) { +// if (!mst.contains(i)) { +// if (weights[i] != 0 && (next == v || weights[i] < weights[next])) { // first check for valid connection, then try to find min weight +// next = i; +// } +// } +// } +// mst.add(next); +// ans += weights[next]; +// +// for (int i = 0; i < v; i++) { +// if (!mst.contains(i)) { +// if (weights[i] == 0 || adjM[next][i] < weights[i]) { // update shortest dist to nodes that are not added to mst yet +// weights[i] = adjM[next][i]; +// } +// } +// } +// } +// return ans; +// } + + public static List getPrimsMST(List graph) { + PriorityQueue pq = new PriorityQueue<>( + (a, b) -> a.getCurrMinDistance() - b.getCurrMinDistance() + ); + + // Values in the map represent the corresponding node with only the edges in the MST + Map nodeToMSTNode = new HashMap<>(); + + // mstEdge map required to track the edges in the MST. The corresponding node is the start node of the edge. + Map mstEdge = new HashMap<>(); + + // Initialize each node's minDistance to infinity and add to the priority queue + for (Node node : graph) { + node.setCurrMinDistance(Integer.MAX_VALUE); + pq.add(node); + nodeToMSTNode.put(node, new Node()); // Create a corresponding MST node } - while (mst.size() != v) { - Pair popped = pq.poll(); - if (mst.contains(popped.getEndNode())) { - continue; - } - minCost += popped.getDist(); - mst.add(popped.getEndNode()); - for (int i = 0; i < v; i++) { - if (mst.contains(i)) { - continue; - } - if (adjM[popped.getEndNode()][i] != 0) { // ensure valid edge - pq.add(new Pair(adjM[popped.getEndNode()][i], i)); - } - } + + // Assuming graph is not empty and the start node is the first node + if (!graph.isEmpty()) { + graph.get(0).setCurrMinDistance(0); } - return minCost; - } - /** - * Alternative implementation that simply uses array to hold weights rather than heap. - * Note: Starts from the node labelled 0 and repeatedly update weights - * which stores the minimum weight from any node in the MST to other nodes. - * Time: O(V) + O(V*2V) - * Space: O(V) - * - * @param adjM Adjacency matrix that encapsulates the distance/weight between nodes - * @return minimum weight of the spanning tree - */ - public int minCostConnectPoints2(int[][] adjM) { - int v = adjM.length; - int[] weights = new int[v]; - - System.arraycopy(adjM[0], 0, weights, 0, v); - - Set mst = new HashSet<>(); - mst.add(0); // start from source 0 - int ans = 0; - while (mst.size() < v) { - int next = v; - for (int i = 0; i < v; i++) { - if (!mst.contains(i)) { - if (weights[i] != 0 && (next == v - || weights[i] < weights[next])) { // check for valid connection, then try to find min weight - next = i; - } - } - } - mst.add(next); - ans += weights[next]; - - for (int i = 0; i < v; i++) { - if (!mst.contains(i)) { - if (weights[i] == 0 - || adjM[next][i] < weights[i]) { // update shortest dist to nodes that are not added to mst yet - weights[i] = adjM[next][i]; - } + while (!pq.isEmpty()) { + Node current = pq.poll(); + current.setVisited(true); + + for (Edge edge : current.getEdges()) { + Node adjacent = edge.getEndNode(); + if (!adjacent.isVisited() && edge.getWeight() < adjacent.getCurrMinDistance()) { + pq.remove(adjacent); + adjacent.setCurrMinDistance(edge.getWeight()); + pq.add(adjacent); + mstEdge.put(edge, current); // Update the lightest valid outgoing edge } } } - return ans; + + // Populate the MST nodes with the edges to be included in the MST + for (Edge edge : mstEdge.keySet()) { + Node start = mstEdge.get(edge); + nodeToMSTNode.get(start).addEdge(edge); + } + + // Extract the nodes from the map to return them + return new ArrayList<>(nodeToMSTNode.values()); } + } + + From 90b54060b286788cfb453f0687ebf27c0cec9f70 Mon Sep 17 00:00:00 2001 From: junneng Date: Sun, 31 Dec 2023 22:08:29 +0800 Subject: [PATCH 12/51] Update docs for Prim's algorithm --- .../java/algorithms/minimumSpanningTree/prims/Prim.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java index b79182ed..076f1c9f 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java @@ -7,10 +7,14 @@ * Idea: * Starting from any source (this will be the first node to be in the MST), * pick the lightest outgoing edge, and include the node at the other end as part of a set of nodes S. - * Now repeatedly do the above by picking the lightest outgoing edge adjacent to any node in S. + * + * Now repeatedly do the above by picking the lightest outgoing edge adjacent to any node in the MST. * (ensuring the other end of the node is not already in the MST) * Repeat until S contains all nodes in the graph. S is the MST. * + * Actual implementation: + * + * * Motivating Example: Minimum Cost to Connect All Points * A -9- C -2- E From 956747d58757175a91734d06a6e14934d84dca80 Mon Sep 17 00:00:00 2001 From: junnengsoo Date: Wed, 31 Jan 2024 11:27:20 +0800 Subject: [PATCH 13/51] Remove Edge implementation, add adjacency list and identifiers --- .../minimumSpanningTree/prims/Edge.java | 24 --- .../minimumSpanningTree/prims/Node.java | 63 ++++---- .../minimumSpanningTree/prims/Prim.java | 145 ++++-------------- 3 files changed, 70 insertions(+), 162 deletions(-) delete mode 100644 src/main/java/algorithms/minimumSpanningTree/prims/Edge.java diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Edge.java b/src/main/java/algorithms/minimumSpanningTree/prims/Edge.java deleted file mode 100644 index 0ca05f86..00000000 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Edge.java +++ /dev/null @@ -1,24 +0,0 @@ -package algorithms.minimumSpanningTree.prims; - -/** - * Helper class to encapsulate information about an edge; - * specifically, tells us the weight of an edge and the node on the other end - * (assumes that the starting node of the edge is known) - */ -public class Edge { - private final int weight; - private final Node endNode; - - public Edge(int weight, Node endNode) { - this.weight = weight; - this.endNode = endNode; - } - - public Node getEndNode() { - return this.endNode; - } - - public int getWeight() { - return this.weight; - } -} \ No newline at end of file diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java index 8f0d33d6..649b0a83 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java @@ -1,52 +1,59 @@ package algorithms.minimumSpanningTree.prims; -import java.util.ArrayList; -import java.util.List; +import java.util.HashMap; +import java.util.Map; import java.util.Objects; -/** - * Helper class to encapsulate information about a node; - * specifically, tells us the weight of an edge and the node on the other end - * (assumes that the starting node of the edge is known) - */ public class Node { - private final List edges; private boolean isVisited = false; - private int currMinDistance; + private int currMinWeight; + private Map adjacentNodes; + private String identifier; // Unique identifier for the node - public Node(List edges) { - this.edges = new ArrayList<>(edges); + public Node(String identifier) { + this.adjacentNodes = new HashMap<>(); + this.identifier = identifier; } - public Node() { - this.edges = new ArrayList<>(); + + public Node(String identifier, Map adjacentNodes) { + this.identifier = identifier; + this.adjacentNodes = adjacentNodes; } - public List getEdges() { - return this.edges; + public Map getAdjacentNodes() { + return adjacentNodes; } - public int getCurrMinDistance() { - return currMinDistance; + public int getCurrMinWeight() { + return currMinWeight; } - public void setVisited(boolean isVisited) { - this.isVisited = isVisited; + public void setCurrMinWeight(int currMinWeight) { + this.currMinWeight = currMinWeight; } public boolean isVisited() { return this.isVisited; } - public void setCurrMinDistance(int currMinDistance) { - this.currMinDistance = currMinDistance; + public void setVisited(boolean isVisited) { + this.isVisited = isVisited; + } + + public String getIdentifier() { + return identifier; } - public String toString() { - return this.edges.toString(); + public void setIdentifier(String identifier) { + this.identifier = identifier; } - public void addEdge(Edge mstEdge) { - this.edges.add(mstEdge); + @Override + public String toString() { + return "Node{" + + "identifier='" + identifier + '\'' + + ", adjacentNodes=" + adjacentNodes + + '}'; } @Override @@ -54,11 +61,13 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Node node = (Node) o; - return isVisited == node.isVisited && edges.equals(node.edges); + return isVisited == node.isVisited && + Objects.equals(identifier, node.identifier) && + Objects.equals(adjacentNodes, node.adjacentNodes); } @Override public int hashCode() { - return Objects.hash(edges, isVisited); + return Objects.hash(identifier, adjacentNodes, isVisited); } } diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java index 076f1c9f..8c358883 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java @@ -1,6 +1,10 @@ package algorithms.minimumSpanningTree.prims; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.PriorityQueue; /** * Implementation of Prim's Algorithm to find MSTs @@ -23,145 +27,64 @@ / / \ / F -1- B --5-- D */ - -/** - * Implementation 1: Using heap - * Time: O(V) + O(ElogV) (since heap could possibly hold E number of weights) + O(E-V) (nodes that have been 'seen' are still added to the heap, just not expanded) + O(V^2) - * Space: O(V) (hashmap to decide on MST) + O(E) (heap) = O(V+E) = O(E) - */ - public class Prim { -// /** -// * points: Adjacency matrix that encapsulates the distance/weight between nodes -// * adjM[i][j] is the weight of the edge connecting points i and j; a value of 0 suggests there is no connection between i and j -// * @param adjM Adjacency matrix that encapsulates the distance/weight between nodes -// * @return minimum weight of the spanning tree -// */ -// public int minCostConnectPoints(int[][] adjM) { -// int v = adjM.length; -// int minCost = 0; -// Set mst = new HashSet<>(); -// mst.add(0); -// PriorityQueue pq = new PriorityQueue<>( -// (a, b) -> a.dist - b.dist -// ); -// for (int i = 0; i < v; i++) { -// if (!mst.contains(i)) { -// if (adjM[0][i] != 0) { // ensure valid edge -// pq.add(new Edge(adjM[0][i], i)); -// } -// } -// } -// while (mst.size() != v) { -// Edge popped = pq.poll(); -// if (mst.contains(popped.endNode)) { -// continue; -// } -// minCost += popped.dist; -// mst.add(popped.endNode); -// for (int i = 0; i < v; i++) { -// if (mst.contains(i)) { -// continue; -// } -// if (adjM[popped.endNode][i] != 0) { // ensure valid edge -// pq.add(new Edge(adjM[popped.endNode][i], i)); -// } -// } -// } -// return minCost; -// } -// -// /** -// * Alternative implementation that simply uses array to hold weights rather than heap. -// * Note: Starts from the node labelled 0 and repeatedly update -// * which stores the minimum weight from any node in the MST to other nodes. -// * Time: O(V) + O(V*2V) -// * Space: O(V) -// * @param adjM Adjacency matrix that encapsulates the distance/weight between nodes -// * @return minimum weight of the spanning tree -// */ -// public int minCostConnectPoints2(int[][] adjM) { -// int v = adjM.length; -// int[] weights = new int[v]; -// -// for (int i = 0; i < v; i++) { -// weights[i] = adjM[0][i]; -// } -// -// Set mst = new HashSet<>(); -// mst.add(0); // start from source 0 -// int ans = 0; -// while (mst.size() < v) { -// int next = v; -// for (int i = 0; i < v; i++) { -// if (!mst.contains(i)) { -// if (weights[i] != 0 && (next == v || weights[i] < weights[next])) { // first check for valid connection, then try to find min weight -// next = i; -// } -// } -// } -// mst.add(next); -// ans += weights[next]; -// -// for (int i = 0; i < v; i++) { -// if (!mst.contains(i)) { -// if (weights[i] == 0 || adjM[next][i] < weights[i]) { // update shortest dist to nodes that are not added to mst yet -// weights[i] = adjM[next][i]; -// } -// } -// } -// } -// return ans; -// } - public static List getPrimsMST(List graph) { PriorityQueue pq = new PriorityQueue<>( - (a, b) -> a.getCurrMinDistance() - b.getCurrMinDistance() + (a, b) -> a.getCurrMinWeight() - b.getCurrMinWeight() ); // Values in the map represent the corresponding node with only the edges in the MST Map nodeToMSTNode = new HashMap<>(); + Map parentInMST = new HashMap<>(); - // mstEdge map required to track the edges in the MST. The corresponding node is the start node of the edge. - Map mstEdge = new HashMap<>(); - - // Initialize each node's minDistance to infinity and add to the priority queue + // Initialize each node's minWeight to infinity and add to the priority queue for (Node node : graph) { - node.setCurrMinDistance(Integer.MAX_VALUE); + node.setCurrMinWeight(Integer.MAX_VALUE); pq.add(node); - nodeToMSTNode.put(node, new Node()); // Create a corresponding MST node + nodeToMSTNode.put(node, new Node(node.getIdentifier())); // Create a corresponding MST node + parentInMST.put(node, null); } // Assuming graph is not empty and the start node is the first node if (!graph.isEmpty()) { - graph.get(0).setCurrMinDistance(0); + graph.get(0).setCurrMinWeight(0); } while (!pq.isEmpty()) { Node current = pq.poll(); current.setVisited(true); - for (Edge edge : current.getEdges()) { - Node adjacent = edge.getEndNode(); - if (!adjacent.isVisited() && edge.getWeight() < adjacent.getCurrMinDistance()) { - pq.remove(adjacent); - adjacent.setCurrMinDistance(edge.getWeight()); - pq.add(adjacent); - mstEdge.put(edge, current); // Update the lightest valid outgoing edge + Map currentAdjacentNodes = current.getAdjacentNodes(); + + for (Map.Entry entry : currentAdjacentNodes.entrySet()) { + Node adjacent = entry.getKey(); + Integer weight = entry.getValue(); + + if (!adjacent.isVisited() && weight < adjacent.getCurrMinWeight()) { + adjacent.setCurrMinWeight(weight); + + // Update the parent in MST + parentInMST.put(adjacent, current); } } } - // Populate the MST nodes with the edges to be included in the MST - for (Edge edge : mstEdge.keySet()) { - Node start = mstEdge.get(edge); - nodeToMSTNode.get(start).addEdge(edge); + // Construct the MST using the parent-child relationships + for (Node originalNode : graph) { + Node mstNode = nodeToMSTNode.get(originalNode); + Node parent = parentInMST.get(originalNode); + + if (parent != null) { + Node mstParent = nodeToMSTNode.get(parent); + int weight = originalNode.getAdjacentNodes().get(parent); + mstParent.getAdjacentNodes().put(mstNode, weight); + mstNode.getAdjacentNodes().put(mstParent, weight); // For undirected graphs + } } // Extract the nodes from the map to return them return new ArrayList<>(nodeToMSTNode.values()); } - } From 70771ce2f62a1d1802c867ad288fe1ea6f3f706d Mon Sep 17 00:00:00 2001 From: junnengsoo Date: Wed, 31 Jan 2024 20:42:14 +0800 Subject: [PATCH 14/51] Add MST tests --- .../minimumSpanningTree/prims/Node.java | 7 +- .../minimumSpanningTree/prims/Prim.java | 4 +- .../minimumSpanningTree/prims/PrimsTest.java | 169 ++++++++++++++++++ 3 files changed, 173 insertions(+), 7 deletions(-) create mode 100644 src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java index 649b0a83..bb91e729 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java @@ -52,7 +52,6 @@ public void setIdentifier(String identifier) { public String toString() { return "Node{" + "identifier='" + identifier + '\'' + - ", adjacentNodes=" + adjacentNodes + '}'; } @@ -61,13 +60,11 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Node node = (Node) o; - return isVisited == node.isVisited && - Objects.equals(identifier, node.identifier) && - Objects.equals(adjacentNodes, node.adjacentNodes); + return Objects.equals(identifier, node.identifier); } @Override public int hashCode() { - return Objects.hash(identifier, adjacentNodes, isVisited); + return Objects.hash(identifier); } } diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java index 8c358883..da4cfff9 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java @@ -61,7 +61,9 @@ public static List getPrimsMST(List graph) { Integer weight = entry.getValue(); if (!adjacent.isVisited() && weight < adjacent.getCurrMinWeight()) { + pq.remove(adjacent); adjacent.setCurrMinWeight(weight); + pq.add(adjacent); // Update the parent in MST parentInMST.put(adjacent, current); @@ -87,5 +89,3 @@ public static List getPrimsMST(List graph) { } } - - diff --git a/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java b/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java new file mode 100644 index 00000000..96bc6784 --- /dev/null +++ b/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java @@ -0,0 +1,169 @@ +package algorithms.minimumSpanningTree.prims; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +public class PrimsTest { + @Test + public void testPrimsMST_SimpleGraph() { + // Graph setup + // A -1- B -1- C + Node nodeActualA = new Node("A"); + Node nodeActualB = new Node("B"); + Node nodeActualC = new Node("C"); + + nodeActualA.getAdjacentNodes().put(nodeActualB, 1); + nodeActualB.getAdjacentNodes().put(nodeActualA, 1); + nodeActualB.getAdjacentNodes().put(nodeActualC, 1); + nodeActualC.getAdjacentNodes().put(nodeActualB, 1); + + List graph = Arrays.asList(nodeActualA, nodeActualB, nodeActualC); + + // Run Prim's algorithm + List actualMST = Prim.getPrimsMST(graph); + + // Expected MST + // A -1- B -1- C + Node nodeExpectedA = new Node("A"); + Node nodeExpectedB = new Node("B"); + Node nodeExpectedC = new Node("C"); + + nodeExpectedA.getAdjacentNodes().put(nodeExpectedB, 1); + nodeExpectedB.getAdjacentNodes().put(nodeExpectedA, 1); + nodeExpectedB.getAdjacentNodes().put(nodeExpectedC, 1); + nodeExpectedC.getAdjacentNodes().put(nodeExpectedB, 1); + + // Expected MST (same as the original graph in this simple case) + List expectedMST = Arrays.asList(nodeExpectedA, nodeExpectedB, nodeExpectedC); + + expectedMST.sort(Comparator.comparing(Node::getIdentifier)); + actualMST.sort(Comparator.comparing(Node::getIdentifier)); + + // Assertion + assertGraphsEqual(expectedMST, actualMST); // Direct comparison of lists + } + + @Test + public void testPrimsMST_ComplexGraph() { + // Graph setup + // A + // / | \ + // 1 4 2 + // / | \ + // B --3-- D + // \ | / + // 2 3 3 + // \ | / + // C + Node nodeA = new Node("A"); + Node nodeB = new Node("B"); + Node nodeC = new Node("C"); + Node nodeD = new Node("D"); + + nodeA.getAdjacentNodes().put(nodeB, 1); + nodeA.getAdjacentNodes().put(nodeC, 4); + nodeA.getAdjacentNodes().put(nodeD, 2); + nodeB.getAdjacentNodes().put(nodeA, 1); + nodeB.getAdjacentNodes().put(nodeC, 3); + nodeB.getAdjacentNodes().put(nodeD, 2); + nodeC.getAdjacentNodes().put(nodeA, 4); + nodeC.getAdjacentNodes().put(nodeB, 3); + nodeC.getAdjacentNodes().put(nodeD, 3); + nodeD.getAdjacentNodes().put(nodeA, 2); + nodeD.getAdjacentNodes().put(nodeB, 2); + nodeD.getAdjacentNodes().put(nodeC, 3); + + List graph = Arrays.asList(nodeA, nodeB, nodeC, nodeD); + + // Run Prim's algorithm + List actualMST = Prim.getPrimsMST(graph); + + // Expected MST + // D -2- A -1- B -3- C + Node nodeExpectedA = new Node("A"); + Node nodeExpectedB = new Node("B"); + Node nodeExpectedC = new Node("C"); + Node nodeExpectedD = new Node("D"); + + nodeExpectedA.getAdjacentNodes().put(nodeExpectedB, 1); + nodeExpectedA.getAdjacentNodes().put(nodeExpectedD, 2); + nodeExpectedB.getAdjacentNodes().put(nodeExpectedA, 1); + nodeExpectedB.getAdjacentNodes().put(nodeExpectedC, 3); + nodeExpectedC.getAdjacentNodes().put(nodeExpectedB, 3); + nodeExpectedD.getAdjacentNodes().put(nodeExpectedA, 2); + + // Expected MST (based on the given graph) + List expectedMST = Arrays.asList(nodeExpectedA, nodeExpectedB, nodeExpectedC, nodeExpectedD); + + expectedMST.sort(Comparator.comparing(Node::getIdentifier)); + actualMST.sort(Comparator.comparing(Node::getIdentifier)); + + // Assertion + assertGraphsEqual(expectedMST, actualMST); // Direct comparison of lists + } + + private void assertGraphsEqual(List expected, List actual) { + if (expected.size() != actual.size()) { + fail("The MSTs do not have the same number of nodes. Expected size: " + + expected.size() + ", Actual size: " + actual.size()); + } + for (int i = 0; i < expected.size(); i++) { + Node expectedNode = expected.get(i); + Node actualNode = actual.get(i); + assertTrue("Nodes do not match at index " + i + ": Expected " + + expectedNode + ", Actual " + actualNode, + nodesAreEqual(expectedNode, actualNode)); + } + } + + private boolean nodesAreEqual(Node node1, Node node2) { + if (!node1.getIdentifier().equals(node2.getIdentifier())) { + fail("Node identifiers do not match: Expected " + + node1.getIdentifier() + ", Actual " + node2.getIdentifier()); + } + if (!nodesHaveSameEdges(node1, node2)) { + fail("Adjacent nodes do not match for Node " + node1.getIdentifier()); + } + return true; + } + + private boolean nodesHaveSameEdges(Node node1, Node node2) { + Map adj1 = node1.getAdjacentNodes(); + Map adj2 = node2.getAdjacentNodes(); + if (adj1.size() != adj2.size()) { + fail("Different number of adjacent nodes for Node " + node1.getIdentifier() + + ". Expected size: " + adj1.size() + ", Actual size: " + adj2.size()); + } + for (Map.Entry entry : adj1.entrySet()) { + Node key = findNodeById(adj2.keySet(), entry.getKey().getIdentifier()); + if (key == null) { + fail("Missing adjacent node '" + entry.getKey().getIdentifier() + + "' in Node " + node1.getIdentifier()); + } + if (!adj2.get(key).equals(entry.getValue())) { + fail("Edge weight does not match for edge " + node1.getIdentifier() + + "-" + key.getIdentifier() + ". Expected weight: " + + entry.getValue() + ", Actual weight: " + adj2.get(key)); + } + } + return true; + } + + + private Node findNodeById(Set nodes, String id) { + for (Node node : nodes) { + if (node.getIdentifier().equals(id)) { + return node; + } + } + return null; + } +} From 5932261100a41968cd534788fe1d44884f56f5d0 Mon Sep 17 00:00:00 2001 From: junnengsoo Date: Wed, 31 Jan 2024 21:22:35 +0800 Subject: [PATCH 15/51] Resolve stylecheck --- .../minimumSpanningTree/prims/Node.java | 39 +++++++++++++++---- .../minimumSpanningTree/prims/Prim.java | 31 +++++---------- .../minimumSpanningTree/prims/PrimsTest.java | 10 ++--- 3 files changed, 46 insertions(+), 34 deletions(-) diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java index bb91e729..2219e5e3 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java @@ -4,17 +4,33 @@ import java.util.Map; import java.util.Objects; +/** + * Node class for Prim's algorithm. + * + * Each node has a unique identifier and contains a Map of adjacent nodes and their corresponding edge weights. + */ public class Node { private boolean isVisited = false; - private int currMinWeight; - private Map adjacentNodes; - private String identifier; // Unique identifier for the node + private int currMinWeight; // Current minimum weight to get to this node to calculate Prim's MST + private final Map adjacentNodes; + private String identifier; + /** + * Constructor for a node with no adjacent nodes. + * + * @param identifier Unique identifier for the node + */ public Node(String identifier) { this.adjacentNodes = new HashMap<>(); this.identifier = identifier; } + /** + * Constructor for a node with a list of adjacent nodes. + * + * @param identifier Unique identifier for the node + * @param adjacentNodes List of adjacent nodes + */ public Node(String identifier, Map adjacentNodes) { this.identifier = identifier; this.adjacentNodes = adjacentNodes; @@ -50,15 +66,22 @@ public void setIdentifier(String identifier) { @Override public String toString() { - return "Node{" + - "identifier='" + identifier + '\'' + - '}'; + return "Node{" + + "identifier='" + + identifier + '\'' + + '}'; } @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + + if (o == null || getClass() != o.getClass()) { + return false; + } + Node node = (Node) o; return Objects.equals(identifier, node.identifier); } diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java index da4cfff9..6a6cf7d5 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java @@ -6,32 +6,21 @@ import java.util.Map; import java.util.PriorityQueue; -/** +/** * Implementation of Prim's Algorithm to find MSTs - * Idea: - * Starting from any source (this will be the first node to be in the MST), - * pick the lightest outgoing edge, and include the node at the other end as part of a set of nodes S. - * - * Now repeatedly do the above by picking the lightest outgoing edge adjacent to any node in the MST. - * (ensuring the other end of the node is not already in the MST) + * Idea: + * Starting from any source (this will be the first node to be in the MST), pick the lightest outgoing edge, and + * include the node at the other end as part of a set of nodes S. Now repeatedly do the above by picking the lightest + * outgoing edge adjacent to any node in the MST (ensure the other end of the node is not already in the MST). * Repeat until S contains all nodes in the graph. S is the MST. - * * Actual implementation: - * - * - * Motivating Example: Minimum Cost to Connect All Points - * - A -9- C -2- E - / / \ \ - 3 4 7 2 - / / \ / - F -1- B --5-- D -*/ + * No Edge class was implemented. Instead, each node has a Map of adjacent nodes and their corresponding edge weights. + * To represent the MST, a new list of nodes is created with the same identifiers as the original graph, with each node + * containing only the edges in the MST. + */ public class Prim { public static List getPrimsMST(List graph) { - PriorityQueue pq = new PriorityQueue<>( - (a, b) -> a.getCurrMinWeight() - b.getCurrMinWeight() - ); + PriorityQueue pq = new PriorityQueue<>((a, b) -> a.getCurrMinWeight() - b.getCurrMinWeight()); // Values in the map represent the corresponding node with only the edges in the MST Map nodeToMSTNode = new HashMap<>(); diff --git a/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java b/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java index 96bc6784..31127790 100644 --- a/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java +++ b/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java @@ -1,6 +1,7 @@ package algorithms.minimumSpanningTree.prims; -import org.junit.Test; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.util.Arrays; import java.util.Comparator; @@ -8,12 +9,11 @@ import java.util.Map; import java.util.Set; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; +import org.junit.Test; public class PrimsTest { @Test - public void testPrimsMST_SimpleGraph() { + public void test_simpleGraph() { // Graph setup // A -1- B -1- C Node nodeActualA = new Node("A"); @@ -52,7 +52,7 @@ public void testPrimsMST_SimpleGraph() { } @Test - public void testPrimsMST_ComplexGraph() { + public void test_complexGraph() { // Graph setup // A // / | \ From 0667d91b70873c1f591dc0eecb80a417d5cd06fd Mon Sep 17 00:00:00 2001 From: junnengsoo Date: Wed, 31 Jan 2024 22:39:30 +0800 Subject: [PATCH 16/51] Add MST README --- docs/assets/images/MST.jpg | Bin 0 -> 37478 bytes docs/assets/images/SPMST.jpg | Bin 0 -> 41740 bytes docs/assets/images/SPOriginal.jpg | Bin 0 -> 52627 bytes docs/assets/images/originalGraph.jpg | Bin 0 -> 44080 bytes .../algorithms/minimumSpanningTree/README.md | 33 ++++++++++++++++++ .../minimumSpanningTree/prims/README.md | 13 +++++++ 6 files changed, 46 insertions(+) create mode 100644 docs/assets/images/MST.jpg create mode 100644 docs/assets/images/SPMST.jpg create mode 100644 docs/assets/images/SPOriginal.jpg create mode 100644 docs/assets/images/originalGraph.jpg create mode 100644 src/main/java/algorithms/minimumSpanningTree/README.md create mode 100644 src/main/java/algorithms/minimumSpanningTree/prims/README.md diff --git a/docs/assets/images/MST.jpg b/docs/assets/images/MST.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1e28b3da91427e74e270b3df771f229a16dddf75 GIT binary patch literal 37478 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 Ptp*YJ6A*{-bLsy9PrM}D literal 0 HcmV?d00001 diff --git a/docs/assets/images/SPMST.jpg b/docs/assets/images/SPMST.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0e7342572a53cbb8d60636e1c27b4f8b1c951a90 GIT binary patch literal 41740 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 Do4U&{ literal 0 HcmV?d00001 diff --git a/docs/assets/images/SPOriginal.jpg b/docs/assets/images/SPOriginal.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0d96f87167f533409ddc86bb5beab326872ab24b GIT binary patch literal 52627 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 Zess2?bQOM`sef*d%1Jg5{{ZWQ|JhGh)o}m- literal 0 HcmV?d00001 diff --git a/src/main/java/algorithms/minimumSpanningTree/README.md b/src/main/java/algorithms/minimumSpanningTree/README.md new file mode 100644 index 00000000..e173d723 --- /dev/null +++ b/src/main/java/algorithms/minimumSpanningTree/README.md @@ -0,0 +1,33 @@ +# Minimum Spanning Tree Algorithms + +## Background + +Minimum Spanning Tree (MST) algorithms are used to find the minimum spanning tree of a weighted, connected graph. A +spanning tree of a graph is a connected, acyclic subgraph that includes all the vertices of the original graph. An MST +is a spanning tree with the minimum possible total edge weight. + +## Prim's Algorithm + +We will discuss more implementation-specific details and complexity analysis in the respective folders. In short, +1. [Prim's Algorithm](prims) is a greedy algorithm that finds the minimum spanning tree of a graph by starting from an +arbitrary node (vertex) and adding the edge with the minimum weight that connects the current tree to a new node, adding +the node to the current tree, until all nodes are included in the tree. + +## Notes + +### Difference between Minimum Spanning Tree and Shortest Path +It is important to note that a Minimum Spanning Tree of a graph does not represent the shortest path between all the +nodes. See below for an example: + +The below graph is a weighted, connected graph with 5 nodes and 6 edges: +![original graph img](../../../../../docs/assets/images/originalGraph.jpg) + +The following is the Minimum Spanning Tree of the above graph: +![MST img](../../../../../docs/assets/images/MST.jpg) + +Taking node A and D into consideration, the shortest path between them is A -> D, with a total weight of 4. +![SPOriginal img](../../../../../docs/assets/images/SPOriginal.jpg) + +However, the shortest path between A and D in the Minimum Spanning Tree is A -> C -> D, with a total weight of 5, which +is not the shortest path in the original graph. +![SPMST img](../../../../../docs/assets/images/SPMST.jpg) diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/README.md b/src/main/java/algorithms/minimumSpanningTree/prims/README.md new file mode 100644 index 00000000..f99d3025 --- /dev/null +++ b/src/main/java/algorithms/minimumSpanningTree/prims/README.md @@ -0,0 +1,13 @@ +# Prim's Algorithm + +## Background + +Prim's Algorithm is a greedy algorithm that finds the minimum spanning tree of a graph by starting from an +arbitrary node (vertex) and adding the edge with the minimum weight that connects the current tree to a new node, adding +the node to the current tree, until all nodes are included in the tree. + +## Complexity Analysis + +## Notes + +### Difference between Prim's Algorithm and Dijkstra's Algorithm \ No newline at end of file From 003140e5948efbf5a92f6629e2d5b556678005b9 Mon Sep 17 00:00:00 2001 From: junnengsoo Date: Tue, 26 Mar 2024 20:22:34 +0800 Subject: [PATCH 17/51] Use adjacency matrix instead of hash map for tracking of nodes --- .../minimumSpanningTree/prims/Node.java | 70 ++++++------------- .../minimumSpanningTree/prims/Prim.java | 63 ++++++----------- 2 files changed, 45 insertions(+), 88 deletions(-) diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java index 2219e5e3..c149e68e 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java @@ -1,45 +1,19 @@ package algorithms.minimumSpanningTree.prims; -import java.util.HashMap; -import java.util.Map; import java.util.Objects; -/** - * Node class for Prim's algorithm. - * - * Each node has a unique identifier and contains a Map of adjacent nodes and their corresponding edge weights. - */ public class Node { private boolean isVisited = false; - private int currMinWeight; // Current minimum weight to get to this node to calculate Prim's MST - private final Map adjacentNodes; + private int currMinWeight = Integer.MAX_VALUE; // Current minimum weight to get to this node + private int index; // Index of this node in the adjacency matrix private String identifier; - /** - * Constructor for a node with no adjacent nodes. - * - * @param identifier Unique identifier for the node - */ - public Node(String identifier) { - this.adjacentNodes = new HashMap<>(); + public Node(String identifier, int index) { this.identifier = identifier; + this.index = index; } - /** - * Constructor for a node with a list of adjacent nodes. - * - * @param identifier Unique identifier for the node - * @param adjacentNodes List of adjacent nodes - */ - public Node(String identifier, Map adjacentNodes) { - this.identifier = identifier; - this.adjacentNodes = adjacentNodes; - } - - public Map getAdjacentNodes() { - return adjacentNodes; - } - + // Getter and setter for currMinWeight public int getCurrMinWeight() { return currMinWeight; } @@ -48,46 +22,46 @@ public void setCurrMinWeight(int currMinWeight) { this.currMinWeight = currMinWeight; } + // Getter and setter for isVisited public boolean isVisited() { - return this.isVisited; + return isVisited; } public void setVisited(boolean isVisited) { this.isVisited = isVisited; } + // Getter for identifier public String getIdentifier() { return identifier; } - public void setIdentifier(String identifier) { - this.identifier = identifier; + // Getter and setter for index + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; } + // toString method @Override public String toString() { - return "Node{" - + "identifier='" - + identifier + '\'' - + '}'; + return "Node{" + "identifier='" + identifier + '\'' + ", index=" + index + '}'; } + // equals and hashCode based on identifier and index @Override public boolean equals(Object o) { - if (this == o) { - return true; - } - - if (o == null || getClass() != o.getClass()) { - return false; - } - + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; Node node = (Node) o; - return Objects.equals(identifier, node.identifier); + return index == node.index && Objects.equals(identifier, node.identifier); } @Override public int hashCode() { - return Objects.hash(identifier); + return Objects.hash(identifier, index); } } diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java index 6a6cf7d5..f5ec6752 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java @@ -19,62 +19,45 @@ * containing only the edges in the MST. */ public class Prim { - public static List getPrimsMST(List graph) { + public static int[][] getPrimsMST(Node[] nodes, int[][] adjacencyMatrix) { PriorityQueue pq = new PriorityQueue<>((a, b) -> a.getCurrMinWeight() - b.getCurrMinWeight()); + int[][] mstMatrix = new int[nodes.length][nodes.length]; // MST adjacency matrix - // Values in the map represent the corresponding node with only the edges in the MST - Map nodeToMSTNode = new HashMap<>(); - Map parentInMST = new HashMap<>(); + // Initialize the MST matrix to represent no edges with Integer.MAX_VALUE + for (int i = 0; i < nodes.length; i++) { + for (int j = 0; j < nodes.length; j++) { + mstMatrix[i][j] = Integer.MAX_VALUE; + } + } - // Initialize each node's minWeight to infinity and add to the priority queue - for (Node node : graph) { + // Initialize all nodes' currMinWeight to infinity, except the first node + for (Node node : nodes) { node.setCurrMinWeight(Integer.MAX_VALUE); pq.add(node); - nodeToMSTNode.put(node, new Node(node.getIdentifier())); // Create a corresponding MST node - parentInMST.put(node, null); - } - - // Assuming graph is not empty and the start node is the first node - if (!graph.isEmpty()) { - graph.get(0).setCurrMinWeight(0); } while (!pq.isEmpty()) { Node current = pq.poll(); current.setVisited(true); - Map currentAdjacentNodes = current.getAdjacentNodes(); - - for (Map.Entry entry : currentAdjacentNodes.entrySet()) { - Node adjacent = entry.getKey(); - Integer weight = entry.getValue(); + int currentIndex = current.getIndex(); - if (!adjacent.isVisited() && weight < adjacent.getCurrMinWeight()) { - pq.remove(adjacent); - adjacent.setCurrMinWeight(weight); - pq.add(adjacent); + for (int i = 0; i < nodes.length; i++) { + if (adjacencyMatrix[currentIndex][i] != Integer.MAX_VALUE && !nodes[i].isVisited()) { + int weight = adjacencyMatrix[currentIndex][i]; - // Update the parent in MST - parentInMST.put(adjacent, current); + if (weight < nodes[i].getCurrMinWeight()) { + pq.remove(nodes[i]); + nodes[i].setCurrMinWeight(weight); + pq.add(nodes[i]); + // Update the MST matrix + mstMatrix[currentIndex][i] = weight; + mstMatrix[i][currentIndex] = weight; // For undirected graphs + } } } } - - // Construct the MST using the parent-child relationships - for (Node originalNode : graph) { - Node mstNode = nodeToMSTNode.get(originalNode); - Node parent = parentInMST.get(originalNode); - - if (parent != null) { - Node mstParent = nodeToMSTNode.get(parent); - int weight = originalNode.getAdjacentNodes().get(parent); - mstParent.getAdjacentNodes().put(mstNode, weight); - mstNode.getAdjacentNodes().put(mstParent, weight); // For undirected graphs - } - } - - // Extract the nodes from the map to return them - return new ArrayList<>(nodeToMSTNode.values()); + return mstMatrix; } } From dec4bd2f7a665743345752660872204ec2a970e0 Mon Sep 17 00:00:00 2001 From: junnengsoo Date: Tue, 26 Mar 2024 22:42:32 +0800 Subject: [PATCH 18/51] Add adjacency matrix and new test cases --- .../minimumSpanningTree/prims/Node.java | 48 ++--- .../minimumSpanningTree/prims/Prim.java | 37 ++-- .../minimumSpanningTree/prims/PrimsTest.java | 192 +++++------------- 3 files changed, 101 insertions(+), 176 deletions(-) diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java index c149e68e..de39584d 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java @@ -2,18 +2,28 @@ import java.util.Objects; +/** + * Node class to represent a node in the graph + */ public class Node { private boolean isVisited = false; private int currMinWeight = Integer.MAX_VALUE; // Current minimum weight to get to this node private int index; // Index of this node in the adjacency matrix - private String identifier; + private final String identifier; + /** + * Constructor + * @param identifier + * @param index + */ public Node(String identifier, int index) { this.identifier = identifier; this.index = index; } - // Getter and setter for currMinWeight + /** + * Getter and setter for currMinWeight + */ public int getCurrMinWeight() { return currMinWeight; } @@ -22,21 +32,26 @@ public void setCurrMinWeight(int currMinWeight) { this.currMinWeight = currMinWeight; } - // Getter and setter for isVisited + /** + * Getter for identifier + * @return identifier + */ public boolean isVisited() { return isVisited; } + /** + * Setter for isVisited + * @param isVisited + */ public void setVisited(boolean isVisited) { this.isVisited = isVisited; } - // Getter for identifier - public String getIdentifier() { - return identifier; - } - - // Getter and setter for index + /** + * Getter for identifier + * @return identifier + */ public int getIndex() { return index; } @@ -45,23 +60,8 @@ public void setIndex(int index) { this.index = index; } - // toString method @Override public String toString() { return "Node{" + "identifier='" + identifier + '\'' + ", index=" + index + '}'; } - - // equals and hashCode based on identifier and index - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Node node = (Node) o; - return index == node.index && Objects.equals(identifier, node.identifier); - } - - @Override - public int hashCode() { - return Objects.hash(identifier, index); - } } diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java index f5ec6752..6466b402 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java @@ -1,9 +1,6 @@ package algorithms.minimumSpanningTree.prims; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.Arrays; import java.util.PriorityQueue; /** @@ -14,19 +11,26 @@ * outgoing edge adjacent to any node in the MST (ensure the other end of the node is not already in the MST). * Repeat until S contains all nodes in the graph. S is the MST. * Actual implementation: - * No Edge class was implemented. Instead, each node has a Map of adjacent nodes and their corresponding edge weights. - * To represent the MST, a new list of nodes is created with the same identifiers as the original graph, with each node - * containing only the edges in the MST. + * No Edge class was implemented. Instead, the weights of the edges are stored in a 2D array adjacency matrix. + * A Node class is implemented to encapsulate a isVisited flag and the current minimum weight to reach the node. */ public class Prim { public static int[][] getPrimsMST(Node[] nodes, int[][] adjacencyMatrix) { PriorityQueue pq = new PriorityQueue<>((a, b) -> a.getCurrMinWeight() - b.getCurrMinWeight()); int[][] mstMatrix = new int[nodes.length][nodes.length]; // MST adjacency matrix - // Initialize the MST matrix to represent no edges with Integer.MAX_VALUE + // Initialize mstMatrix with all edges set to Integer.MAX_VALUE + for (int[] row : mstMatrix) { + Arrays.fill(row, Integer.MAX_VALUE); + } + + int[] parent = new int[nodes.length]; // To track the parent node of each node in the MST + Arrays.fill(parent, -1); // Initialize parent array with -1, indicating no parent + + // Initialize the MST matrix to represent no edges with Integer.MAX_VALUE and 0 for self loops for (int i = 0; i < nodes.length; i++) { for (int j = 0; j < nodes.length; j++) { - mstMatrix[i][j] = Integer.MAX_VALUE; + mstMatrix[i][j] = (i == j) ? 0 : Integer.MAX_VALUE; } } @@ -50,13 +54,22 @@ public static int[][] getPrimsMST(Node[] nodes, int[][] adjacencyMatrix) { pq.remove(nodes[i]); nodes[i].setCurrMinWeight(weight); pq.add(nodes[i]); - // Update the MST matrix - mstMatrix[currentIndex][i] = weight; - mstMatrix[i][currentIndex] = weight; // For undirected graphs + parent[i] = currentIndex; // Set current node as parent of adjacent node } } } } + + // Build MST matrix based on parent array + for (int i = 1; i < nodes.length; i++) { + int p = parent[i]; + if (p != -1) { + int weight = adjacencyMatrix[p][i]; + mstMatrix[p][i] = weight; + mstMatrix[i][p] = weight; // For undirected graphs + } + } + return mstMatrix; } } diff --git a/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java b/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java index 31127790..36830e82 100644 --- a/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java +++ b/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java @@ -1,169 +1,81 @@ package algorithms.minimumSpanningTree.prims; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.Arrays; -import java.util.Comparator; -import java.util.List; -import java.util.Map; -import java.util.Set; +import static org.junit.Assert.assertArrayEquals; import org.junit.Test; public class PrimsTest { + @Test public void test_simpleGraph() { - // Graph setup + // Graph setup (Adjacency Matrix) // A -1- B -1- C - Node nodeActualA = new Node("A"); - Node nodeActualB = new Node("B"); - Node nodeActualC = new Node("C"); - - nodeActualA.getAdjacentNodes().put(nodeActualB, 1); - nodeActualB.getAdjacentNodes().put(nodeActualA, 1); - nodeActualB.getAdjacentNodes().put(nodeActualC, 1); - nodeActualC.getAdjacentNodes().put(nodeActualB, 1); - - List graph = Arrays.asList(nodeActualA, nodeActualB, nodeActualC); + int[][] adjacencyMatrix = { + {0, 1, 1}, // A: A-B, A-C + {1, 0, 1}, // B: B-A, B-C + {1, 1, 0} // C: C-A, C-B + }; + + Node[] nodes = { + new Node("A", 0), + new Node("B", 1), + new Node("C", 2) + }; // Run Prim's algorithm - List actualMST = Prim.getPrimsMST(graph); + int[][] actualMST = Prim.getPrimsMST(nodes, adjacencyMatrix); // Expected MST // A -1- B -1- C - Node nodeExpectedA = new Node("A"); - Node nodeExpectedB = new Node("B"); - Node nodeExpectedC = new Node("C"); - - nodeExpectedA.getAdjacentNodes().put(nodeExpectedB, 1); - nodeExpectedB.getAdjacentNodes().put(nodeExpectedA, 1); - nodeExpectedB.getAdjacentNodes().put(nodeExpectedC, 1); - nodeExpectedC.getAdjacentNodes().put(nodeExpectedB, 1); - - // Expected MST (same as the original graph in this simple case) - List expectedMST = Arrays.asList(nodeExpectedA, nodeExpectedB, nodeExpectedC); - - expectedMST.sort(Comparator.comparing(Node::getIdentifier)); - actualMST.sort(Comparator.comparing(Node::getIdentifier)); + int[][] expectedMST = { + {0, 1, 1}, // A: A-B, A-C + {1, 0, Integer.MAX_VALUE}, // B: B-A + {1, Integer.MAX_VALUE, 0} // C: C-A + }; // Assertion - assertGraphsEqual(expectedMST, actualMST); // Direct comparison of lists + assertArrayEquals(expectedMST, actualMST); } @Test public void test_complexGraph() { // Graph setup - // A - // / | \ - // 1 4 2 - // / | \ - // B --3-- D - // \ | / - // 2 3 3 - // \ | / - // C - Node nodeA = new Node("A"); - Node nodeB = new Node("B"); - Node nodeC = new Node("C"); - Node nodeD = new Node("D"); - - nodeA.getAdjacentNodes().put(nodeB, 1); - nodeA.getAdjacentNodes().put(nodeC, 4); - nodeA.getAdjacentNodes().put(nodeD, 2); - nodeB.getAdjacentNodes().put(nodeA, 1); - nodeB.getAdjacentNodes().put(nodeC, 3); - nodeB.getAdjacentNodes().put(nodeD, 2); - nodeC.getAdjacentNodes().put(nodeA, 4); - nodeC.getAdjacentNodes().put(nodeB, 3); - nodeC.getAdjacentNodes().put(nodeD, 3); - nodeD.getAdjacentNodes().put(nodeA, 2); - nodeD.getAdjacentNodes().put(nodeB, 2); - nodeD.getAdjacentNodes().put(nodeC, 3); - - List graph = Arrays.asList(nodeA, nodeB, nodeC, nodeD); + // A + // / | \ + // 1 4 2 + /// | \ + //B --3-- D + // \ | / + // 2 4 3 + // \|/ + // C + int[][] adjacencyMatrix = { + {0, 1, 4, 2}, // A: A-B, A-C, A-D + {1, 0, 2, 3}, // B: B-A, B-C, B-D + {4, 2, 0, 3}, // C: C-A, C-B, C-D + {2, 3, 3, 0} // D: D-A, D-B, D-C + }; + + Node[] nodes = { + new Node("A", 0), + new Node("B", 1), + new Node("C", 2), + new Node("D", 3) + }; // Run Prim's algorithm - List actualMST = Prim.getPrimsMST(graph); + int[][] actualMST = Prim.getPrimsMST(nodes, adjacencyMatrix); // Expected MST - // D -2- A -1- B -3- C - Node nodeExpectedA = new Node("A"); - Node nodeExpectedB = new Node("B"); - Node nodeExpectedC = new Node("C"); - Node nodeExpectedD = new Node("D"); - - nodeExpectedA.getAdjacentNodes().put(nodeExpectedB, 1); - nodeExpectedA.getAdjacentNodes().put(nodeExpectedD, 2); - nodeExpectedB.getAdjacentNodes().put(nodeExpectedA, 1); - nodeExpectedB.getAdjacentNodes().put(nodeExpectedC, 3); - nodeExpectedC.getAdjacentNodes().put(nodeExpectedB, 3); - nodeExpectedD.getAdjacentNodes().put(nodeExpectedA, 2); - - // Expected MST (based on the given graph) - List expectedMST = Arrays.asList(nodeExpectedA, nodeExpectedB, nodeExpectedC, nodeExpectedD); - - expectedMST.sort(Comparator.comparing(Node::getIdentifier)); - actualMST.sort(Comparator.comparing(Node::getIdentifier)); + // Based on the graph, assuming the MST is correctly computed + int[][] expectedMST = { + {0, 1, Integer.MAX_VALUE, 2}, // A: A-B, A-D + {1, 0, 2, Integer.MAX_VALUE}, // B: B-A, B-C + {Integer.MAX_VALUE, 2, 0, Integer.MAX_VALUE}, // C: C-B + {2, Integer.MAX_VALUE, Integer.MAX_VALUE, 0} // D: D-A + }; // Assertion - assertGraphsEqual(expectedMST, actualMST); // Direct comparison of lists - } - - private void assertGraphsEqual(List expected, List actual) { - if (expected.size() != actual.size()) { - fail("The MSTs do not have the same number of nodes. Expected size: " - + expected.size() + ", Actual size: " + actual.size()); - } - for (int i = 0; i < expected.size(); i++) { - Node expectedNode = expected.get(i); - Node actualNode = actual.get(i); - assertTrue("Nodes do not match at index " + i + ": Expected " - + expectedNode + ", Actual " + actualNode, - nodesAreEqual(expectedNode, actualNode)); - } - } - - private boolean nodesAreEqual(Node node1, Node node2) { - if (!node1.getIdentifier().equals(node2.getIdentifier())) { - fail("Node identifiers do not match: Expected " - + node1.getIdentifier() + ", Actual " + node2.getIdentifier()); - } - if (!nodesHaveSameEdges(node1, node2)) { - fail("Adjacent nodes do not match for Node " + node1.getIdentifier()); - } - return true; - } - - private boolean nodesHaveSameEdges(Node node1, Node node2) { - Map adj1 = node1.getAdjacentNodes(); - Map adj2 = node2.getAdjacentNodes(); - if (adj1.size() != adj2.size()) { - fail("Different number of adjacent nodes for Node " + node1.getIdentifier() - + ". Expected size: " + adj1.size() + ", Actual size: " + adj2.size()); - } - for (Map.Entry entry : adj1.entrySet()) { - Node key = findNodeById(adj2.keySet(), entry.getKey().getIdentifier()); - if (key == null) { - fail("Missing adjacent node '" + entry.getKey().getIdentifier() - + "' in Node " + node1.getIdentifier()); - } - if (!adj2.get(key).equals(entry.getValue())) { - fail("Edge weight does not match for edge " + node1.getIdentifier() - + "-" + key.getIdentifier() + ". Expected weight: " - + entry.getValue() + ", Actual weight: " + adj2.get(key)); - } - } - return true; - } - - - private Node findNodeById(Set nodes, String id) { - for (Node node : nodes) { - if (node.getIdentifier().equals(id)) { - return node; - } - } - return null; + assertArrayEquals(expectedMST, actualMST); } } From a93535f66e19fc7822461c2fd8c9cc6d06d57a5e Mon Sep 17 00:00:00 2001 From: junneng Date: Sun, 31 Dec 2023 21:31:19 +0800 Subject: [PATCH 19/51] Add Prim's algorithm --- .../minimumSpanningTree/prims/Edge.java | 24 +++ .../minimumSpanningTree/prims/Node.java | 64 +++++++ .../minimumSpanningTree/prims/Prim.java | 164 ++++++++++++++++++ 3 files changed, 252 insertions(+) create mode 100644 src/main/java/algorithms/minimumSpanningTree/prims/Edge.java create mode 100644 src/main/java/algorithms/minimumSpanningTree/prims/Node.java create mode 100644 src/main/java/algorithms/minimumSpanningTree/prims/Prim.java diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Edge.java b/src/main/java/algorithms/minimumSpanningTree/prims/Edge.java new file mode 100644 index 00000000..0ca05f86 --- /dev/null +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Edge.java @@ -0,0 +1,24 @@ +package algorithms.minimumSpanningTree.prims; + +/** + * Helper class to encapsulate information about an edge; + * specifically, tells us the weight of an edge and the node on the other end + * (assumes that the starting node of the edge is known) + */ +public class Edge { + private final int weight; + private final Node endNode; + + public Edge(int weight, Node endNode) { + this.weight = weight; + this.endNode = endNode; + } + + public Node getEndNode() { + return this.endNode; + } + + public int getWeight() { + return this.weight; + } +} \ No newline at end of file diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java new file mode 100644 index 00000000..8f0d33d6 --- /dev/null +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java @@ -0,0 +1,64 @@ +package algorithms.minimumSpanningTree.prims; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * Helper class to encapsulate information about a node; + * specifically, tells us the weight of an edge and the node on the other end + * (assumes that the starting node of the edge is known) + */ +public class Node { + private final List edges; + private boolean isVisited = false; + private int currMinDistance; + + public Node(List edges) { + this.edges = new ArrayList<>(edges); + } + public Node() { + this.edges = new ArrayList<>(); + } + + public List getEdges() { + return this.edges; + } + + public int getCurrMinDistance() { + return currMinDistance; + } + + public void setVisited(boolean isVisited) { + this.isVisited = isVisited; + } + + public boolean isVisited() { + return this.isVisited; + } + + public void setCurrMinDistance(int currMinDistance) { + this.currMinDistance = currMinDistance; + } + + public String toString() { + return this.edges.toString(); + } + + public void addEdge(Edge mstEdge) { + this.edges.add(mstEdge); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Node node = (Node) o; + return isVisited == node.isVisited && edges.equals(node.edges); + } + + @Override + public int hashCode() { + return Objects.hash(edges, isVisited); + } +} diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java new file mode 100644 index 00000000..b79182ed --- /dev/null +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java @@ -0,0 +1,164 @@ +package algorithms.minimumSpanningTree.prims; + +import java.util.*; + +/** + * Implementation of Prim's Algorithm to find MSTs + * Idea: + * Starting from any source (this will be the first node to be in the MST), + * pick the lightest outgoing edge, and include the node at the other end as part of a set of nodes S. + * Now repeatedly do the above by picking the lightest outgoing edge adjacent to any node in S. + * (ensuring the other end of the node is not already in the MST) + * Repeat until S contains all nodes in the graph. S is the MST. + * + * Motivating Example: Minimum Cost to Connect All Points + * + A -9- C -2- E + / / \ \ + 3 4 7 2 + / / \ / + F -1- B --5-- D +*/ + +/** + * Implementation 1: Using heap + * Time: O(V) + O(ElogV) (since heap could possibly hold E number of weights) + O(E-V) (nodes that have been 'seen' are still added to the heap, just not expanded) + O(V^2) + * Space: O(V) (hashmap to decide on MST) + O(E) (heap) = O(V+E) = O(E) + */ + +public class Prim { +// /** +// * points: Adjacency matrix that encapsulates the distance/weight between nodes +// * adjM[i][j] is the weight of the edge connecting points i and j; a value of 0 suggests there is no connection between i and j +// * @param adjM Adjacency matrix that encapsulates the distance/weight between nodes +// * @return minimum weight of the spanning tree +// */ +// public int minCostConnectPoints(int[][] adjM) { +// int v = adjM.length; +// int minCost = 0; +// Set mst = new HashSet<>(); +// mst.add(0); +// PriorityQueue pq = new PriorityQueue<>( +// (a, b) -> a.dist - b.dist +// ); +// for (int i = 0; i < v; i++) { +// if (!mst.contains(i)) { +// if (adjM[0][i] != 0) { // ensure valid edge +// pq.add(new Edge(adjM[0][i], i)); +// } +// } +// } +// while (mst.size() != v) { +// Edge popped = pq.poll(); +// if (mst.contains(popped.endNode)) { +// continue; +// } +// minCost += popped.dist; +// mst.add(popped.endNode); +// for (int i = 0; i < v; i++) { +// if (mst.contains(i)) { +// continue; +// } +// if (adjM[popped.endNode][i] != 0) { // ensure valid edge +// pq.add(new Edge(adjM[popped.endNode][i], i)); +// } +// } +// } +// return minCost; +// } +// +// /** +// * Alternative implementation that simply uses array to hold weights rather than heap. +// * Note: Starts from the node labelled 0 and repeatedly update +// * which stores the minimum weight from any node in the MST to other nodes. +// * Time: O(V) + O(V*2V) +// * Space: O(V) +// * @param adjM Adjacency matrix that encapsulates the distance/weight between nodes +// * @return minimum weight of the spanning tree +// */ +// public int minCostConnectPoints2(int[][] adjM) { +// int v = adjM.length; +// int[] weights = new int[v]; +// +// for (int i = 0; i < v; i++) { +// weights[i] = adjM[0][i]; +// } +// +// Set mst = new HashSet<>(); +// mst.add(0); // start from source 0 +// int ans = 0; +// while (mst.size() < v) { +// int next = v; +// for (int i = 0; i < v; i++) { +// if (!mst.contains(i)) { +// if (weights[i] != 0 && (next == v || weights[i] < weights[next])) { // first check for valid connection, then try to find min weight +// next = i; +// } +// } +// } +// mst.add(next); +// ans += weights[next]; +// +// for (int i = 0; i < v; i++) { +// if (!mst.contains(i)) { +// if (weights[i] == 0 || adjM[next][i] < weights[i]) { // update shortest dist to nodes that are not added to mst yet +// weights[i] = adjM[next][i]; +// } +// } +// } +// } +// return ans; +// } + + public static List getPrimsMST(List graph) { + PriorityQueue pq = new PriorityQueue<>( + (a, b) -> a.getCurrMinDistance() - b.getCurrMinDistance() + ); + + // Values in the map represent the corresponding node with only the edges in the MST + Map nodeToMSTNode = new HashMap<>(); + + // mstEdge map required to track the edges in the MST. The corresponding node is the start node of the edge. + Map mstEdge = new HashMap<>(); + + // Initialize each node's minDistance to infinity and add to the priority queue + for (Node node : graph) { + node.setCurrMinDistance(Integer.MAX_VALUE); + pq.add(node); + nodeToMSTNode.put(node, new Node()); // Create a corresponding MST node + } + + // Assuming graph is not empty and the start node is the first node + if (!graph.isEmpty()) { + graph.get(0).setCurrMinDistance(0); + } + + while (!pq.isEmpty()) { + Node current = pq.poll(); + current.setVisited(true); + + for (Edge edge : current.getEdges()) { + Node adjacent = edge.getEndNode(); + if (!adjacent.isVisited() && edge.getWeight() < adjacent.getCurrMinDistance()) { + pq.remove(adjacent); + adjacent.setCurrMinDistance(edge.getWeight()); + pq.add(adjacent); + mstEdge.put(edge, current); // Update the lightest valid outgoing edge + } + } + } + + // Populate the MST nodes with the edges to be included in the MST + for (Edge edge : mstEdge.keySet()) { + Node start = mstEdge.get(edge); + nodeToMSTNode.get(start).addEdge(edge); + } + + // Extract the nodes from the map to return them + return new ArrayList<>(nodeToMSTNode.values()); + } + +} + + + From 3e2bdfe68753e7aa85a51cb2a487c6f78ed0cfeb Mon Sep 17 00:00:00 2001 From: junneng Date: Sun, 31 Dec 2023 22:08:29 +0800 Subject: [PATCH 20/51] Update docs for Prim's algorithm --- .../java/algorithms/minimumSpanningTree/prims/Prim.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java index b79182ed..076f1c9f 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java @@ -7,10 +7,14 @@ * Idea: * Starting from any source (this will be the first node to be in the MST), * pick the lightest outgoing edge, and include the node at the other end as part of a set of nodes S. - * Now repeatedly do the above by picking the lightest outgoing edge adjacent to any node in S. + * + * Now repeatedly do the above by picking the lightest outgoing edge adjacent to any node in the MST. * (ensuring the other end of the node is not already in the MST) * Repeat until S contains all nodes in the graph. S is the MST. * + * Actual implementation: + * + * * Motivating Example: Minimum Cost to Connect All Points * A -9- C -2- E From dac6a618deb7036b9f2593ba7ac25ed33b1221b9 Mon Sep 17 00:00:00 2001 From: junnengsoo Date: Wed, 31 Jan 2024 11:27:20 +0800 Subject: [PATCH 21/51] Remove Edge implementation, add adjacency list and identifiers --- .../minimumSpanningTree/prims/Edge.java | 24 --- .../minimumSpanningTree/prims/Node.java | 63 ++++---- .../minimumSpanningTree/prims/Prim.java | 145 ++++-------------- 3 files changed, 70 insertions(+), 162 deletions(-) delete mode 100644 src/main/java/algorithms/minimumSpanningTree/prims/Edge.java diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Edge.java b/src/main/java/algorithms/minimumSpanningTree/prims/Edge.java deleted file mode 100644 index 0ca05f86..00000000 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Edge.java +++ /dev/null @@ -1,24 +0,0 @@ -package algorithms.minimumSpanningTree.prims; - -/** - * Helper class to encapsulate information about an edge; - * specifically, tells us the weight of an edge and the node on the other end - * (assumes that the starting node of the edge is known) - */ -public class Edge { - private final int weight; - private final Node endNode; - - public Edge(int weight, Node endNode) { - this.weight = weight; - this.endNode = endNode; - } - - public Node getEndNode() { - return this.endNode; - } - - public int getWeight() { - return this.weight; - } -} \ No newline at end of file diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java index 8f0d33d6..649b0a83 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java @@ -1,52 +1,59 @@ package algorithms.minimumSpanningTree.prims; -import java.util.ArrayList; -import java.util.List; +import java.util.HashMap; +import java.util.Map; import java.util.Objects; -/** - * Helper class to encapsulate information about a node; - * specifically, tells us the weight of an edge and the node on the other end - * (assumes that the starting node of the edge is known) - */ public class Node { - private final List edges; private boolean isVisited = false; - private int currMinDistance; + private int currMinWeight; + private Map adjacentNodes; + private String identifier; // Unique identifier for the node - public Node(List edges) { - this.edges = new ArrayList<>(edges); + public Node(String identifier) { + this.adjacentNodes = new HashMap<>(); + this.identifier = identifier; } - public Node() { - this.edges = new ArrayList<>(); + + public Node(String identifier, Map adjacentNodes) { + this.identifier = identifier; + this.adjacentNodes = adjacentNodes; } - public List getEdges() { - return this.edges; + public Map getAdjacentNodes() { + return adjacentNodes; } - public int getCurrMinDistance() { - return currMinDistance; + public int getCurrMinWeight() { + return currMinWeight; } - public void setVisited(boolean isVisited) { - this.isVisited = isVisited; + public void setCurrMinWeight(int currMinWeight) { + this.currMinWeight = currMinWeight; } public boolean isVisited() { return this.isVisited; } - public void setCurrMinDistance(int currMinDistance) { - this.currMinDistance = currMinDistance; + public void setVisited(boolean isVisited) { + this.isVisited = isVisited; + } + + public String getIdentifier() { + return identifier; } - public String toString() { - return this.edges.toString(); + public void setIdentifier(String identifier) { + this.identifier = identifier; } - public void addEdge(Edge mstEdge) { - this.edges.add(mstEdge); + @Override + public String toString() { + return "Node{" + + "identifier='" + identifier + '\'' + + ", adjacentNodes=" + adjacentNodes + + '}'; } @Override @@ -54,11 +61,13 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Node node = (Node) o; - return isVisited == node.isVisited && edges.equals(node.edges); + return isVisited == node.isVisited && + Objects.equals(identifier, node.identifier) && + Objects.equals(adjacentNodes, node.adjacentNodes); } @Override public int hashCode() { - return Objects.hash(edges, isVisited); + return Objects.hash(identifier, adjacentNodes, isVisited); } } diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java index 076f1c9f..8c358883 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java @@ -1,6 +1,10 @@ package algorithms.minimumSpanningTree.prims; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.PriorityQueue; /** * Implementation of Prim's Algorithm to find MSTs @@ -23,145 +27,64 @@ / / \ / F -1- B --5-- D */ - -/** - * Implementation 1: Using heap - * Time: O(V) + O(ElogV) (since heap could possibly hold E number of weights) + O(E-V) (nodes that have been 'seen' are still added to the heap, just not expanded) + O(V^2) - * Space: O(V) (hashmap to decide on MST) + O(E) (heap) = O(V+E) = O(E) - */ - public class Prim { -// /** -// * points: Adjacency matrix that encapsulates the distance/weight between nodes -// * adjM[i][j] is the weight of the edge connecting points i and j; a value of 0 suggests there is no connection between i and j -// * @param adjM Adjacency matrix that encapsulates the distance/weight between nodes -// * @return minimum weight of the spanning tree -// */ -// public int minCostConnectPoints(int[][] adjM) { -// int v = adjM.length; -// int minCost = 0; -// Set mst = new HashSet<>(); -// mst.add(0); -// PriorityQueue pq = new PriorityQueue<>( -// (a, b) -> a.dist - b.dist -// ); -// for (int i = 0; i < v; i++) { -// if (!mst.contains(i)) { -// if (adjM[0][i] != 0) { // ensure valid edge -// pq.add(new Edge(adjM[0][i], i)); -// } -// } -// } -// while (mst.size() != v) { -// Edge popped = pq.poll(); -// if (mst.contains(popped.endNode)) { -// continue; -// } -// minCost += popped.dist; -// mst.add(popped.endNode); -// for (int i = 0; i < v; i++) { -// if (mst.contains(i)) { -// continue; -// } -// if (adjM[popped.endNode][i] != 0) { // ensure valid edge -// pq.add(new Edge(adjM[popped.endNode][i], i)); -// } -// } -// } -// return minCost; -// } -// -// /** -// * Alternative implementation that simply uses array to hold weights rather than heap. -// * Note: Starts from the node labelled 0 and repeatedly update -// * which stores the minimum weight from any node in the MST to other nodes. -// * Time: O(V) + O(V*2V) -// * Space: O(V) -// * @param adjM Adjacency matrix that encapsulates the distance/weight between nodes -// * @return minimum weight of the spanning tree -// */ -// public int minCostConnectPoints2(int[][] adjM) { -// int v = adjM.length; -// int[] weights = new int[v]; -// -// for (int i = 0; i < v; i++) { -// weights[i] = adjM[0][i]; -// } -// -// Set mst = new HashSet<>(); -// mst.add(0); // start from source 0 -// int ans = 0; -// while (mst.size() < v) { -// int next = v; -// for (int i = 0; i < v; i++) { -// if (!mst.contains(i)) { -// if (weights[i] != 0 && (next == v || weights[i] < weights[next])) { // first check for valid connection, then try to find min weight -// next = i; -// } -// } -// } -// mst.add(next); -// ans += weights[next]; -// -// for (int i = 0; i < v; i++) { -// if (!mst.contains(i)) { -// if (weights[i] == 0 || adjM[next][i] < weights[i]) { // update shortest dist to nodes that are not added to mst yet -// weights[i] = adjM[next][i]; -// } -// } -// } -// } -// return ans; -// } - public static List getPrimsMST(List graph) { PriorityQueue pq = new PriorityQueue<>( - (a, b) -> a.getCurrMinDistance() - b.getCurrMinDistance() + (a, b) -> a.getCurrMinWeight() - b.getCurrMinWeight() ); // Values in the map represent the corresponding node with only the edges in the MST Map nodeToMSTNode = new HashMap<>(); + Map parentInMST = new HashMap<>(); - // mstEdge map required to track the edges in the MST. The corresponding node is the start node of the edge. - Map mstEdge = new HashMap<>(); - - // Initialize each node's minDistance to infinity and add to the priority queue + // Initialize each node's minWeight to infinity and add to the priority queue for (Node node : graph) { - node.setCurrMinDistance(Integer.MAX_VALUE); + node.setCurrMinWeight(Integer.MAX_VALUE); pq.add(node); - nodeToMSTNode.put(node, new Node()); // Create a corresponding MST node + nodeToMSTNode.put(node, new Node(node.getIdentifier())); // Create a corresponding MST node + parentInMST.put(node, null); } // Assuming graph is not empty and the start node is the first node if (!graph.isEmpty()) { - graph.get(0).setCurrMinDistance(0); + graph.get(0).setCurrMinWeight(0); } while (!pq.isEmpty()) { Node current = pq.poll(); current.setVisited(true); - for (Edge edge : current.getEdges()) { - Node adjacent = edge.getEndNode(); - if (!adjacent.isVisited() && edge.getWeight() < adjacent.getCurrMinDistance()) { - pq.remove(adjacent); - adjacent.setCurrMinDistance(edge.getWeight()); - pq.add(adjacent); - mstEdge.put(edge, current); // Update the lightest valid outgoing edge + Map currentAdjacentNodes = current.getAdjacentNodes(); + + for (Map.Entry entry : currentAdjacentNodes.entrySet()) { + Node adjacent = entry.getKey(); + Integer weight = entry.getValue(); + + if (!adjacent.isVisited() && weight < adjacent.getCurrMinWeight()) { + adjacent.setCurrMinWeight(weight); + + // Update the parent in MST + parentInMST.put(adjacent, current); } } } - // Populate the MST nodes with the edges to be included in the MST - for (Edge edge : mstEdge.keySet()) { - Node start = mstEdge.get(edge); - nodeToMSTNode.get(start).addEdge(edge); + // Construct the MST using the parent-child relationships + for (Node originalNode : graph) { + Node mstNode = nodeToMSTNode.get(originalNode); + Node parent = parentInMST.get(originalNode); + + if (parent != null) { + Node mstParent = nodeToMSTNode.get(parent); + int weight = originalNode.getAdjacentNodes().get(parent); + mstParent.getAdjacentNodes().put(mstNode, weight); + mstNode.getAdjacentNodes().put(mstParent, weight); // For undirected graphs + } } // Extract the nodes from the map to return them return new ArrayList<>(nodeToMSTNode.values()); } - } From 776dc24e98b082a7757671ed9db2c1757b5bd082 Mon Sep 17 00:00:00 2001 From: junnengsoo Date: Wed, 31 Jan 2024 20:42:14 +0800 Subject: [PATCH 22/51] Add MST tests --- .../minimumSpanningTree/prims/Node.java | 7 +- .../minimumSpanningTree/prims/Prim.java | 4 +- .../minimumSpanningTree/prims/PrimsTest.java | 169 ++++++++++++++++++ 3 files changed, 173 insertions(+), 7 deletions(-) create mode 100644 src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java index 649b0a83..bb91e729 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java @@ -52,7 +52,6 @@ public void setIdentifier(String identifier) { public String toString() { return "Node{" + "identifier='" + identifier + '\'' + - ", adjacentNodes=" + adjacentNodes + '}'; } @@ -61,13 +60,11 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Node node = (Node) o; - return isVisited == node.isVisited && - Objects.equals(identifier, node.identifier) && - Objects.equals(adjacentNodes, node.adjacentNodes); + return Objects.equals(identifier, node.identifier); } @Override public int hashCode() { - return Objects.hash(identifier, adjacentNodes, isVisited); + return Objects.hash(identifier); } } diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java index 8c358883..da4cfff9 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java @@ -61,7 +61,9 @@ public static List getPrimsMST(List graph) { Integer weight = entry.getValue(); if (!adjacent.isVisited() && weight < adjacent.getCurrMinWeight()) { + pq.remove(adjacent); adjacent.setCurrMinWeight(weight); + pq.add(adjacent); // Update the parent in MST parentInMST.put(adjacent, current); @@ -87,5 +89,3 @@ public static List getPrimsMST(List graph) { } } - - diff --git a/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java b/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java new file mode 100644 index 00000000..96bc6784 --- /dev/null +++ b/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java @@ -0,0 +1,169 @@ +package algorithms.minimumSpanningTree.prims; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +public class PrimsTest { + @Test + public void testPrimsMST_SimpleGraph() { + // Graph setup + // A -1- B -1- C + Node nodeActualA = new Node("A"); + Node nodeActualB = new Node("B"); + Node nodeActualC = new Node("C"); + + nodeActualA.getAdjacentNodes().put(nodeActualB, 1); + nodeActualB.getAdjacentNodes().put(nodeActualA, 1); + nodeActualB.getAdjacentNodes().put(nodeActualC, 1); + nodeActualC.getAdjacentNodes().put(nodeActualB, 1); + + List graph = Arrays.asList(nodeActualA, nodeActualB, nodeActualC); + + // Run Prim's algorithm + List actualMST = Prim.getPrimsMST(graph); + + // Expected MST + // A -1- B -1- C + Node nodeExpectedA = new Node("A"); + Node nodeExpectedB = new Node("B"); + Node nodeExpectedC = new Node("C"); + + nodeExpectedA.getAdjacentNodes().put(nodeExpectedB, 1); + nodeExpectedB.getAdjacentNodes().put(nodeExpectedA, 1); + nodeExpectedB.getAdjacentNodes().put(nodeExpectedC, 1); + nodeExpectedC.getAdjacentNodes().put(nodeExpectedB, 1); + + // Expected MST (same as the original graph in this simple case) + List expectedMST = Arrays.asList(nodeExpectedA, nodeExpectedB, nodeExpectedC); + + expectedMST.sort(Comparator.comparing(Node::getIdentifier)); + actualMST.sort(Comparator.comparing(Node::getIdentifier)); + + // Assertion + assertGraphsEqual(expectedMST, actualMST); // Direct comparison of lists + } + + @Test + public void testPrimsMST_ComplexGraph() { + // Graph setup + // A + // / | \ + // 1 4 2 + // / | \ + // B --3-- D + // \ | / + // 2 3 3 + // \ | / + // C + Node nodeA = new Node("A"); + Node nodeB = new Node("B"); + Node nodeC = new Node("C"); + Node nodeD = new Node("D"); + + nodeA.getAdjacentNodes().put(nodeB, 1); + nodeA.getAdjacentNodes().put(nodeC, 4); + nodeA.getAdjacentNodes().put(nodeD, 2); + nodeB.getAdjacentNodes().put(nodeA, 1); + nodeB.getAdjacentNodes().put(nodeC, 3); + nodeB.getAdjacentNodes().put(nodeD, 2); + nodeC.getAdjacentNodes().put(nodeA, 4); + nodeC.getAdjacentNodes().put(nodeB, 3); + nodeC.getAdjacentNodes().put(nodeD, 3); + nodeD.getAdjacentNodes().put(nodeA, 2); + nodeD.getAdjacentNodes().put(nodeB, 2); + nodeD.getAdjacentNodes().put(nodeC, 3); + + List graph = Arrays.asList(nodeA, nodeB, nodeC, nodeD); + + // Run Prim's algorithm + List actualMST = Prim.getPrimsMST(graph); + + // Expected MST + // D -2- A -1- B -3- C + Node nodeExpectedA = new Node("A"); + Node nodeExpectedB = new Node("B"); + Node nodeExpectedC = new Node("C"); + Node nodeExpectedD = new Node("D"); + + nodeExpectedA.getAdjacentNodes().put(nodeExpectedB, 1); + nodeExpectedA.getAdjacentNodes().put(nodeExpectedD, 2); + nodeExpectedB.getAdjacentNodes().put(nodeExpectedA, 1); + nodeExpectedB.getAdjacentNodes().put(nodeExpectedC, 3); + nodeExpectedC.getAdjacentNodes().put(nodeExpectedB, 3); + nodeExpectedD.getAdjacentNodes().put(nodeExpectedA, 2); + + // Expected MST (based on the given graph) + List expectedMST = Arrays.asList(nodeExpectedA, nodeExpectedB, nodeExpectedC, nodeExpectedD); + + expectedMST.sort(Comparator.comparing(Node::getIdentifier)); + actualMST.sort(Comparator.comparing(Node::getIdentifier)); + + // Assertion + assertGraphsEqual(expectedMST, actualMST); // Direct comparison of lists + } + + private void assertGraphsEqual(List expected, List actual) { + if (expected.size() != actual.size()) { + fail("The MSTs do not have the same number of nodes. Expected size: " + + expected.size() + ", Actual size: " + actual.size()); + } + for (int i = 0; i < expected.size(); i++) { + Node expectedNode = expected.get(i); + Node actualNode = actual.get(i); + assertTrue("Nodes do not match at index " + i + ": Expected " + + expectedNode + ", Actual " + actualNode, + nodesAreEqual(expectedNode, actualNode)); + } + } + + private boolean nodesAreEqual(Node node1, Node node2) { + if (!node1.getIdentifier().equals(node2.getIdentifier())) { + fail("Node identifiers do not match: Expected " + + node1.getIdentifier() + ", Actual " + node2.getIdentifier()); + } + if (!nodesHaveSameEdges(node1, node2)) { + fail("Adjacent nodes do not match for Node " + node1.getIdentifier()); + } + return true; + } + + private boolean nodesHaveSameEdges(Node node1, Node node2) { + Map adj1 = node1.getAdjacentNodes(); + Map adj2 = node2.getAdjacentNodes(); + if (adj1.size() != adj2.size()) { + fail("Different number of adjacent nodes for Node " + node1.getIdentifier() + + ". Expected size: " + adj1.size() + ", Actual size: " + adj2.size()); + } + for (Map.Entry entry : adj1.entrySet()) { + Node key = findNodeById(adj2.keySet(), entry.getKey().getIdentifier()); + if (key == null) { + fail("Missing adjacent node '" + entry.getKey().getIdentifier() + + "' in Node " + node1.getIdentifier()); + } + if (!adj2.get(key).equals(entry.getValue())) { + fail("Edge weight does not match for edge " + node1.getIdentifier() + + "-" + key.getIdentifier() + ". Expected weight: " + + entry.getValue() + ", Actual weight: " + adj2.get(key)); + } + } + return true; + } + + + private Node findNodeById(Set nodes, String id) { + for (Node node : nodes) { + if (node.getIdentifier().equals(id)) { + return node; + } + } + return null; + } +} From f67cf0f0690c64f5c37f26220dfebbbf328c731d Mon Sep 17 00:00:00 2001 From: junnengsoo Date: Wed, 31 Jan 2024 21:22:35 +0800 Subject: [PATCH 23/51] Resolve stylecheck --- .../minimumSpanningTree/prims/Node.java | 39 +++++++++++++++---- .../minimumSpanningTree/prims/Prim.java | 31 +++++---------- .../minimumSpanningTree/prims/PrimsTest.java | 10 ++--- 3 files changed, 46 insertions(+), 34 deletions(-) diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java index bb91e729..2219e5e3 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java @@ -4,17 +4,33 @@ import java.util.Map; import java.util.Objects; +/** + * Node class for Prim's algorithm. + * + * Each node has a unique identifier and contains a Map of adjacent nodes and their corresponding edge weights. + */ public class Node { private boolean isVisited = false; - private int currMinWeight; - private Map adjacentNodes; - private String identifier; // Unique identifier for the node + private int currMinWeight; // Current minimum weight to get to this node to calculate Prim's MST + private final Map adjacentNodes; + private String identifier; + /** + * Constructor for a node with no adjacent nodes. + * + * @param identifier Unique identifier for the node + */ public Node(String identifier) { this.adjacentNodes = new HashMap<>(); this.identifier = identifier; } + /** + * Constructor for a node with a list of adjacent nodes. + * + * @param identifier Unique identifier for the node + * @param adjacentNodes List of adjacent nodes + */ public Node(String identifier, Map adjacentNodes) { this.identifier = identifier; this.adjacentNodes = adjacentNodes; @@ -50,15 +66,22 @@ public void setIdentifier(String identifier) { @Override public String toString() { - return "Node{" + - "identifier='" + identifier + '\'' + - '}'; + return "Node{" + + "identifier='" + + identifier + '\'' + + '}'; } @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + + if (o == null || getClass() != o.getClass()) { + return false; + } + Node node = (Node) o; return Objects.equals(identifier, node.identifier); } diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java index da4cfff9..6a6cf7d5 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java @@ -6,32 +6,21 @@ import java.util.Map; import java.util.PriorityQueue; -/** +/** * Implementation of Prim's Algorithm to find MSTs - * Idea: - * Starting from any source (this will be the first node to be in the MST), - * pick the lightest outgoing edge, and include the node at the other end as part of a set of nodes S. - * - * Now repeatedly do the above by picking the lightest outgoing edge adjacent to any node in the MST. - * (ensuring the other end of the node is not already in the MST) + * Idea: + * Starting from any source (this will be the first node to be in the MST), pick the lightest outgoing edge, and + * include the node at the other end as part of a set of nodes S. Now repeatedly do the above by picking the lightest + * outgoing edge adjacent to any node in the MST (ensure the other end of the node is not already in the MST). * Repeat until S contains all nodes in the graph. S is the MST. - * * Actual implementation: - * - * - * Motivating Example: Minimum Cost to Connect All Points - * - A -9- C -2- E - / / \ \ - 3 4 7 2 - / / \ / - F -1- B --5-- D -*/ + * No Edge class was implemented. Instead, each node has a Map of adjacent nodes and their corresponding edge weights. + * To represent the MST, a new list of nodes is created with the same identifiers as the original graph, with each node + * containing only the edges in the MST. + */ public class Prim { public static List getPrimsMST(List graph) { - PriorityQueue pq = new PriorityQueue<>( - (a, b) -> a.getCurrMinWeight() - b.getCurrMinWeight() - ); + PriorityQueue pq = new PriorityQueue<>((a, b) -> a.getCurrMinWeight() - b.getCurrMinWeight()); // Values in the map represent the corresponding node with only the edges in the MST Map nodeToMSTNode = new HashMap<>(); diff --git a/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java b/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java index 96bc6784..31127790 100644 --- a/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java +++ b/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java @@ -1,6 +1,7 @@ package algorithms.minimumSpanningTree.prims; -import org.junit.Test; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.util.Arrays; import java.util.Comparator; @@ -8,12 +9,11 @@ import java.util.Map; import java.util.Set; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; +import org.junit.Test; public class PrimsTest { @Test - public void testPrimsMST_SimpleGraph() { + public void test_simpleGraph() { // Graph setup // A -1- B -1- C Node nodeActualA = new Node("A"); @@ -52,7 +52,7 @@ public void testPrimsMST_SimpleGraph() { } @Test - public void testPrimsMST_ComplexGraph() { + public void test_complexGraph() { // Graph setup // A // / | \ From 2fdafe0136a75e720b48ad76642f1b0025eb7d7e Mon Sep 17 00:00:00 2001 From: junnengsoo Date: Wed, 31 Jan 2024 22:39:30 +0800 Subject: [PATCH 24/51] Add MST README --- docs/assets/images/MST.jpg | Bin 0 -> 37478 bytes docs/assets/images/SPMST.jpg | Bin 0 -> 41740 bytes docs/assets/images/SPOriginal.jpg | Bin 0 -> 52627 bytes docs/assets/images/originalGraph.jpg | Bin 0 -> 44080 bytes .../algorithms/minimumSpanningTree/README.md | 33 ++++++++++++++++++ .../minimumSpanningTree/prims/README.md | 13 +++++++ 6 files changed, 46 insertions(+) create mode 100644 docs/assets/images/MST.jpg create mode 100644 docs/assets/images/SPMST.jpg create mode 100644 docs/assets/images/SPOriginal.jpg create mode 100644 docs/assets/images/originalGraph.jpg create mode 100644 src/main/java/algorithms/minimumSpanningTree/README.md create mode 100644 src/main/java/algorithms/minimumSpanningTree/prims/README.md diff --git a/docs/assets/images/MST.jpg b/docs/assets/images/MST.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1e28b3da91427e74e270b3df771f229a16dddf75 GIT binary patch literal 37478 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 Ptp*YJ6A*{-bLsy9PrM}D literal 0 HcmV?d00001 diff --git a/docs/assets/images/SPMST.jpg b/docs/assets/images/SPMST.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0e7342572a53cbb8d60636e1c27b4f8b1c951a90 GIT binary patch literal 41740 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 Do4U&{ literal 0 HcmV?d00001 diff --git a/docs/assets/images/SPOriginal.jpg b/docs/assets/images/SPOriginal.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0d96f87167f533409ddc86bb5beab326872ab24b GIT binary patch literal 52627 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 Zess2?bQOM`sef*d%1Jg5{{ZWQ|JhGh)o}m- literal 0 HcmV?d00001 diff --git a/src/main/java/algorithms/minimumSpanningTree/README.md b/src/main/java/algorithms/minimumSpanningTree/README.md new file mode 100644 index 00000000..e173d723 --- /dev/null +++ b/src/main/java/algorithms/minimumSpanningTree/README.md @@ -0,0 +1,33 @@ +# Minimum Spanning Tree Algorithms + +## Background + +Minimum Spanning Tree (MST) algorithms are used to find the minimum spanning tree of a weighted, connected graph. A +spanning tree of a graph is a connected, acyclic subgraph that includes all the vertices of the original graph. An MST +is a spanning tree with the minimum possible total edge weight. + +## Prim's Algorithm + +We will discuss more implementation-specific details and complexity analysis in the respective folders. In short, +1. [Prim's Algorithm](prims) is a greedy algorithm that finds the minimum spanning tree of a graph by starting from an +arbitrary node (vertex) and adding the edge with the minimum weight that connects the current tree to a new node, adding +the node to the current tree, until all nodes are included in the tree. + +## Notes + +### Difference between Minimum Spanning Tree and Shortest Path +It is important to note that a Minimum Spanning Tree of a graph does not represent the shortest path between all the +nodes. See below for an example: + +The below graph is a weighted, connected graph with 5 nodes and 6 edges: +![original graph img](../../../../../docs/assets/images/originalGraph.jpg) + +The following is the Minimum Spanning Tree of the above graph: +![MST img](../../../../../docs/assets/images/MST.jpg) + +Taking node A and D into consideration, the shortest path between them is A -> D, with a total weight of 4. +![SPOriginal img](../../../../../docs/assets/images/SPOriginal.jpg) + +However, the shortest path between A and D in the Minimum Spanning Tree is A -> C -> D, with a total weight of 5, which +is not the shortest path in the original graph. +![SPMST img](../../../../../docs/assets/images/SPMST.jpg) diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/README.md b/src/main/java/algorithms/minimumSpanningTree/prims/README.md new file mode 100644 index 00000000..f99d3025 --- /dev/null +++ b/src/main/java/algorithms/minimumSpanningTree/prims/README.md @@ -0,0 +1,13 @@ +# Prim's Algorithm + +## Background + +Prim's Algorithm is a greedy algorithm that finds the minimum spanning tree of a graph by starting from an +arbitrary node (vertex) and adding the edge with the minimum weight that connects the current tree to a new node, adding +the node to the current tree, until all nodes are included in the tree. + +## Complexity Analysis + +## Notes + +### Difference between Prim's Algorithm and Dijkstra's Algorithm \ No newline at end of file From f9b262042694588b7f7f61c9f7e68a7eabc3f8af Mon Sep 17 00:00:00 2001 From: junnengsoo Date: Tue, 26 Mar 2024 20:22:34 +0800 Subject: [PATCH 25/51] Use adjacency matrix instead of hash map for tracking of nodes --- .../minimumSpanningTree/prims/Node.java | 70 ++++++------------- .../minimumSpanningTree/prims/Prim.java | 63 ++++++----------- 2 files changed, 45 insertions(+), 88 deletions(-) diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java index 2219e5e3..c149e68e 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java @@ -1,45 +1,19 @@ package algorithms.minimumSpanningTree.prims; -import java.util.HashMap; -import java.util.Map; import java.util.Objects; -/** - * Node class for Prim's algorithm. - * - * Each node has a unique identifier and contains a Map of adjacent nodes and their corresponding edge weights. - */ public class Node { private boolean isVisited = false; - private int currMinWeight; // Current minimum weight to get to this node to calculate Prim's MST - private final Map adjacentNodes; + private int currMinWeight = Integer.MAX_VALUE; // Current minimum weight to get to this node + private int index; // Index of this node in the adjacency matrix private String identifier; - /** - * Constructor for a node with no adjacent nodes. - * - * @param identifier Unique identifier for the node - */ - public Node(String identifier) { - this.adjacentNodes = new HashMap<>(); + public Node(String identifier, int index) { this.identifier = identifier; + this.index = index; } - /** - * Constructor for a node with a list of adjacent nodes. - * - * @param identifier Unique identifier for the node - * @param adjacentNodes List of adjacent nodes - */ - public Node(String identifier, Map adjacentNodes) { - this.identifier = identifier; - this.adjacentNodes = adjacentNodes; - } - - public Map getAdjacentNodes() { - return adjacentNodes; - } - + // Getter and setter for currMinWeight public int getCurrMinWeight() { return currMinWeight; } @@ -48,46 +22,46 @@ public void setCurrMinWeight(int currMinWeight) { this.currMinWeight = currMinWeight; } + // Getter and setter for isVisited public boolean isVisited() { - return this.isVisited; + return isVisited; } public void setVisited(boolean isVisited) { this.isVisited = isVisited; } + // Getter for identifier public String getIdentifier() { return identifier; } - public void setIdentifier(String identifier) { - this.identifier = identifier; + // Getter and setter for index + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; } + // toString method @Override public String toString() { - return "Node{" - + "identifier='" - + identifier + '\'' - + '}'; + return "Node{" + "identifier='" + identifier + '\'' + ", index=" + index + '}'; } + // equals and hashCode based on identifier and index @Override public boolean equals(Object o) { - if (this == o) { - return true; - } - - if (o == null || getClass() != o.getClass()) { - return false; - } - + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; Node node = (Node) o; - return Objects.equals(identifier, node.identifier); + return index == node.index && Objects.equals(identifier, node.identifier); } @Override public int hashCode() { - return Objects.hash(identifier); + return Objects.hash(identifier, index); } } diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java index 6a6cf7d5..f5ec6752 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java @@ -19,62 +19,45 @@ * containing only the edges in the MST. */ public class Prim { - public static List getPrimsMST(List graph) { + public static int[][] getPrimsMST(Node[] nodes, int[][] adjacencyMatrix) { PriorityQueue pq = new PriorityQueue<>((a, b) -> a.getCurrMinWeight() - b.getCurrMinWeight()); + int[][] mstMatrix = new int[nodes.length][nodes.length]; // MST adjacency matrix - // Values in the map represent the corresponding node with only the edges in the MST - Map nodeToMSTNode = new HashMap<>(); - Map parentInMST = new HashMap<>(); + // Initialize the MST matrix to represent no edges with Integer.MAX_VALUE + for (int i = 0; i < nodes.length; i++) { + for (int j = 0; j < nodes.length; j++) { + mstMatrix[i][j] = Integer.MAX_VALUE; + } + } - // Initialize each node's minWeight to infinity and add to the priority queue - for (Node node : graph) { + // Initialize all nodes' currMinWeight to infinity, except the first node + for (Node node : nodes) { node.setCurrMinWeight(Integer.MAX_VALUE); pq.add(node); - nodeToMSTNode.put(node, new Node(node.getIdentifier())); // Create a corresponding MST node - parentInMST.put(node, null); - } - - // Assuming graph is not empty and the start node is the first node - if (!graph.isEmpty()) { - graph.get(0).setCurrMinWeight(0); } while (!pq.isEmpty()) { Node current = pq.poll(); current.setVisited(true); - Map currentAdjacentNodes = current.getAdjacentNodes(); - - for (Map.Entry entry : currentAdjacentNodes.entrySet()) { - Node adjacent = entry.getKey(); - Integer weight = entry.getValue(); + int currentIndex = current.getIndex(); - if (!adjacent.isVisited() && weight < adjacent.getCurrMinWeight()) { - pq.remove(adjacent); - adjacent.setCurrMinWeight(weight); - pq.add(adjacent); + for (int i = 0; i < nodes.length; i++) { + if (adjacencyMatrix[currentIndex][i] != Integer.MAX_VALUE && !nodes[i].isVisited()) { + int weight = adjacencyMatrix[currentIndex][i]; - // Update the parent in MST - parentInMST.put(adjacent, current); + if (weight < nodes[i].getCurrMinWeight()) { + pq.remove(nodes[i]); + nodes[i].setCurrMinWeight(weight); + pq.add(nodes[i]); + // Update the MST matrix + mstMatrix[currentIndex][i] = weight; + mstMatrix[i][currentIndex] = weight; // For undirected graphs + } } } } - - // Construct the MST using the parent-child relationships - for (Node originalNode : graph) { - Node mstNode = nodeToMSTNode.get(originalNode); - Node parent = parentInMST.get(originalNode); - - if (parent != null) { - Node mstParent = nodeToMSTNode.get(parent); - int weight = originalNode.getAdjacentNodes().get(parent); - mstParent.getAdjacentNodes().put(mstNode, weight); - mstNode.getAdjacentNodes().put(mstParent, weight); // For undirected graphs - } - } - - // Extract the nodes from the map to return them - return new ArrayList<>(nodeToMSTNode.values()); + return mstMatrix; } } From 7f842085605ccdaac701736cd67d48a661c79915 Mon Sep 17 00:00:00 2001 From: junnengsoo Date: Tue, 26 Mar 2024 22:42:32 +0800 Subject: [PATCH 26/51] Add adjacency matrix and new test cases --- .../minimumSpanningTree/prims/Node.java | 48 ++--- .../minimumSpanningTree/prims/Prim.java | 37 ++-- .../minimumSpanningTree/prims/PrimsTest.java | 192 +++++------------- 3 files changed, 101 insertions(+), 176 deletions(-) diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java index c149e68e..de39584d 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java @@ -2,18 +2,28 @@ import java.util.Objects; +/** + * Node class to represent a node in the graph + */ public class Node { private boolean isVisited = false; private int currMinWeight = Integer.MAX_VALUE; // Current minimum weight to get to this node private int index; // Index of this node in the adjacency matrix - private String identifier; + private final String identifier; + /** + * Constructor + * @param identifier + * @param index + */ public Node(String identifier, int index) { this.identifier = identifier; this.index = index; } - // Getter and setter for currMinWeight + /** + * Getter and setter for currMinWeight + */ public int getCurrMinWeight() { return currMinWeight; } @@ -22,21 +32,26 @@ public void setCurrMinWeight(int currMinWeight) { this.currMinWeight = currMinWeight; } - // Getter and setter for isVisited + /** + * Getter for identifier + * @return identifier + */ public boolean isVisited() { return isVisited; } + /** + * Setter for isVisited + * @param isVisited + */ public void setVisited(boolean isVisited) { this.isVisited = isVisited; } - // Getter for identifier - public String getIdentifier() { - return identifier; - } - - // Getter and setter for index + /** + * Getter for identifier + * @return identifier + */ public int getIndex() { return index; } @@ -45,23 +60,8 @@ public void setIndex(int index) { this.index = index; } - // toString method @Override public String toString() { return "Node{" + "identifier='" + identifier + '\'' + ", index=" + index + '}'; } - - // equals and hashCode based on identifier and index - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Node node = (Node) o; - return index == node.index && Objects.equals(identifier, node.identifier); - } - - @Override - public int hashCode() { - return Objects.hash(identifier, index); - } } diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java index f5ec6752..6466b402 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java @@ -1,9 +1,6 @@ package algorithms.minimumSpanningTree.prims; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.Arrays; import java.util.PriorityQueue; /** @@ -14,19 +11,26 @@ * outgoing edge adjacent to any node in the MST (ensure the other end of the node is not already in the MST). * Repeat until S contains all nodes in the graph. S is the MST. * Actual implementation: - * No Edge class was implemented. Instead, each node has a Map of adjacent nodes and their corresponding edge weights. - * To represent the MST, a new list of nodes is created with the same identifiers as the original graph, with each node - * containing only the edges in the MST. + * No Edge class was implemented. Instead, the weights of the edges are stored in a 2D array adjacency matrix. + * A Node class is implemented to encapsulate a isVisited flag and the current minimum weight to reach the node. */ public class Prim { public static int[][] getPrimsMST(Node[] nodes, int[][] adjacencyMatrix) { PriorityQueue pq = new PriorityQueue<>((a, b) -> a.getCurrMinWeight() - b.getCurrMinWeight()); int[][] mstMatrix = new int[nodes.length][nodes.length]; // MST adjacency matrix - // Initialize the MST matrix to represent no edges with Integer.MAX_VALUE + // Initialize mstMatrix with all edges set to Integer.MAX_VALUE + for (int[] row : mstMatrix) { + Arrays.fill(row, Integer.MAX_VALUE); + } + + int[] parent = new int[nodes.length]; // To track the parent node of each node in the MST + Arrays.fill(parent, -1); // Initialize parent array with -1, indicating no parent + + // Initialize the MST matrix to represent no edges with Integer.MAX_VALUE and 0 for self loops for (int i = 0; i < nodes.length; i++) { for (int j = 0; j < nodes.length; j++) { - mstMatrix[i][j] = Integer.MAX_VALUE; + mstMatrix[i][j] = (i == j) ? 0 : Integer.MAX_VALUE; } } @@ -50,13 +54,22 @@ public static int[][] getPrimsMST(Node[] nodes, int[][] adjacencyMatrix) { pq.remove(nodes[i]); nodes[i].setCurrMinWeight(weight); pq.add(nodes[i]); - // Update the MST matrix - mstMatrix[currentIndex][i] = weight; - mstMatrix[i][currentIndex] = weight; // For undirected graphs + parent[i] = currentIndex; // Set current node as parent of adjacent node } } } } + + // Build MST matrix based on parent array + for (int i = 1; i < nodes.length; i++) { + int p = parent[i]; + if (p != -1) { + int weight = adjacencyMatrix[p][i]; + mstMatrix[p][i] = weight; + mstMatrix[i][p] = weight; // For undirected graphs + } + } + return mstMatrix; } } diff --git a/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java b/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java index 31127790..36830e82 100644 --- a/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java +++ b/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java @@ -1,169 +1,81 @@ package algorithms.minimumSpanningTree.prims; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.Arrays; -import java.util.Comparator; -import java.util.List; -import java.util.Map; -import java.util.Set; +import static org.junit.Assert.assertArrayEquals; import org.junit.Test; public class PrimsTest { + @Test public void test_simpleGraph() { - // Graph setup + // Graph setup (Adjacency Matrix) // A -1- B -1- C - Node nodeActualA = new Node("A"); - Node nodeActualB = new Node("B"); - Node nodeActualC = new Node("C"); - - nodeActualA.getAdjacentNodes().put(nodeActualB, 1); - nodeActualB.getAdjacentNodes().put(nodeActualA, 1); - nodeActualB.getAdjacentNodes().put(nodeActualC, 1); - nodeActualC.getAdjacentNodes().put(nodeActualB, 1); - - List graph = Arrays.asList(nodeActualA, nodeActualB, nodeActualC); + int[][] adjacencyMatrix = { + {0, 1, 1}, // A: A-B, A-C + {1, 0, 1}, // B: B-A, B-C + {1, 1, 0} // C: C-A, C-B + }; + + Node[] nodes = { + new Node("A", 0), + new Node("B", 1), + new Node("C", 2) + }; // Run Prim's algorithm - List actualMST = Prim.getPrimsMST(graph); + int[][] actualMST = Prim.getPrimsMST(nodes, adjacencyMatrix); // Expected MST // A -1- B -1- C - Node nodeExpectedA = new Node("A"); - Node nodeExpectedB = new Node("B"); - Node nodeExpectedC = new Node("C"); - - nodeExpectedA.getAdjacentNodes().put(nodeExpectedB, 1); - nodeExpectedB.getAdjacentNodes().put(nodeExpectedA, 1); - nodeExpectedB.getAdjacentNodes().put(nodeExpectedC, 1); - nodeExpectedC.getAdjacentNodes().put(nodeExpectedB, 1); - - // Expected MST (same as the original graph in this simple case) - List expectedMST = Arrays.asList(nodeExpectedA, nodeExpectedB, nodeExpectedC); - - expectedMST.sort(Comparator.comparing(Node::getIdentifier)); - actualMST.sort(Comparator.comparing(Node::getIdentifier)); + int[][] expectedMST = { + {0, 1, 1}, // A: A-B, A-C + {1, 0, Integer.MAX_VALUE}, // B: B-A + {1, Integer.MAX_VALUE, 0} // C: C-A + }; // Assertion - assertGraphsEqual(expectedMST, actualMST); // Direct comparison of lists + assertArrayEquals(expectedMST, actualMST); } @Test public void test_complexGraph() { // Graph setup - // A - // / | \ - // 1 4 2 - // / | \ - // B --3-- D - // \ | / - // 2 3 3 - // \ | / - // C - Node nodeA = new Node("A"); - Node nodeB = new Node("B"); - Node nodeC = new Node("C"); - Node nodeD = new Node("D"); - - nodeA.getAdjacentNodes().put(nodeB, 1); - nodeA.getAdjacentNodes().put(nodeC, 4); - nodeA.getAdjacentNodes().put(nodeD, 2); - nodeB.getAdjacentNodes().put(nodeA, 1); - nodeB.getAdjacentNodes().put(nodeC, 3); - nodeB.getAdjacentNodes().put(nodeD, 2); - nodeC.getAdjacentNodes().put(nodeA, 4); - nodeC.getAdjacentNodes().put(nodeB, 3); - nodeC.getAdjacentNodes().put(nodeD, 3); - nodeD.getAdjacentNodes().put(nodeA, 2); - nodeD.getAdjacentNodes().put(nodeB, 2); - nodeD.getAdjacentNodes().put(nodeC, 3); - - List graph = Arrays.asList(nodeA, nodeB, nodeC, nodeD); + // A + // / | \ + // 1 4 2 + /// | \ + //B --3-- D + // \ | / + // 2 4 3 + // \|/ + // C + int[][] adjacencyMatrix = { + {0, 1, 4, 2}, // A: A-B, A-C, A-D + {1, 0, 2, 3}, // B: B-A, B-C, B-D + {4, 2, 0, 3}, // C: C-A, C-B, C-D + {2, 3, 3, 0} // D: D-A, D-B, D-C + }; + + Node[] nodes = { + new Node("A", 0), + new Node("B", 1), + new Node("C", 2), + new Node("D", 3) + }; // Run Prim's algorithm - List actualMST = Prim.getPrimsMST(graph); + int[][] actualMST = Prim.getPrimsMST(nodes, adjacencyMatrix); // Expected MST - // D -2- A -1- B -3- C - Node nodeExpectedA = new Node("A"); - Node nodeExpectedB = new Node("B"); - Node nodeExpectedC = new Node("C"); - Node nodeExpectedD = new Node("D"); - - nodeExpectedA.getAdjacentNodes().put(nodeExpectedB, 1); - nodeExpectedA.getAdjacentNodes().put(nodeExpectedD, 2); - nodeExpectedB.getAdjacentNodes().put(nodeExpectedA, 1); - nodeExpectedB.getAdjacentNodes().put(nodeExpectedC, 3); - nodeExpectedC.getAdjacentNodes().put(nodeExpectedB, 3); - nodeExpectedD.getAdjacentNodes().put(nodeExpectedA, 2); - - // Expected MST (based on the given graph) - List expectedMST = Arrays.asList(nodeExpectedA, nodeExpectedB, nodeExpectedC, nodeExpectedD); - - expectedMST.sort(Comparator.comparing(Node::getIdentifier)); - actualMST.sort(Comparator.comparing(Node::getIdentifier)); + // Based on the graph, assuming the MST is correctly computed + int[][] expectedMST = { + {0, 1, Integer.MAX_VALUE, 2}, // A: A-B, A-D + {1, 0, 2, Integer.MAX_VALUE}, // B: B-A, B-C + {Integer.MAX_VALUE, 2, 0, Integer.MAX_VALUE}, // C: C-B + {2, Integer.MAX_VALUE, Integer.MAX_VALUE, 0} // D: D-A + }; // Assertion - assertGraphsEqual(expectedMST, actualMST); // Direct comparison of lists - } - - private void assertGraphsEqual(List expected, List actual) { - if (expected.size() != actual.size()) { - fail("The MSTs do not have the same number of nodes. Expected size: " - + expected.size() + ", Actual size: " + actual.size()); - } - for (int i = 0; i < expected.size(); i++) { - Node expectedNode = expected.get(i); - Node actualNode = actual.get(i); - assertTrue("Nodes do not match at index " + i + ": Expected " - + expectedNode + ", Actual " + actualNode, - nodesAreEqual(expectedNode, actualNode)); - } - } - - private boolean nodesAreEqual(Node node1, Node node2) { - if (!node1.getIdentifier().equals(node2.getIdentifier())) { - fail("Node identifiers do not match: Expected " - + node1.getIdentifier() + ", Actual " + node2.getIdentifier()); - } - if (!nodesHaveSameEdges(node1, node2)) { - fail("Adjacent nodes do not match for Node " + node1.getIdentifier()); - } - return true; - } - - private boolean nodesHaveSameEdges(Node node1, Node node2) { - Map adj1 = node1.getAdjacentNodes(); - Map adj2 = node2.getAdjacentNodes(); - if (adj1.size() != adj2.size()) { - fail("Different number of adjacent nodes for Node " + node1.getIdentifier() - + ". Expected size: " + adj1.size() + ", Actual size: " + adj2.size()); - } - for (Map.Entry entry : adj1.entrySet()) { - Node key = findNodeById(adj2.keySet(), entry.getKey().getIdentifier()); - if (key == null) { - fail("Missing adjacent node '" + entry.getKey().getIdentifier() - + "' in Node " + node1.getIdentifier()); - } - if (!adj2.get(key).equals(entry.getValue())) { - fail("Edge weight does not match for edge " + node1.getIdentifier() - + "-" + key.getIdentifier() + ". Expected weight: " - + entry.getValue() + ", Actual weight: " + adj2.get(key)); - } - } - return true; - } - - - private Node findNodeById(Set nodes, String id) { - for (Node node : nodes) { - if (node.getIdentifier().equals(id)) { - return node; - } - } - return null; + assertArrayEquals(expectedMST, actualMST); } } From 2b2602c20e7823933daa4bb1507862b27842aae4 Mon Sep 17 00:00:00 2001 From: junnengsoo Date: Wed, 27 Mar 2024 16:20:47 +0800 Subject: [PATCH 27/51] Add README --- .../minimumSpanningTree/prims/Node.java | 46 ++++++++----------- .../minimumSpanningTree/prims/Prim.java | 29 +++++++----- .../minimumSpanningTree/prims/README.md | 39 ++++++++++++++-- .../minimumSpanningTree/prims/PrimsTest.java | 28 ++++++----- 4 files changed, 88 insertions(+), 54 deletions(-) diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java index de39584d..fb465f00 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java @@ -1,24 +1,36 @@ package algorithms.minimumSpanningTree.prims; -import java.util.Objects; - /** * Node class to represent a node in the graph + * Note: In our Node class, we do not allow the currMinWeight to be updated after initialization to prevent any + * reference issues in the PriorityQueue. */ public class Node { - private boolean isVisited = false; - private int currMinWeight = Integer.MAX_VALUE; // Current minimum weight to get to this node + private final int currMinWeight; // Current minimum weight to get to this node private int index; // Index of this node in the adjacency matrix private final String identifier; /** - * Constructor + * Constructor for Node + * @param identifier + * @param index + * @param currMinWeight + */ + public Node(String identifier, int index, int currMinWeight) { + this.identifier = identifier; + this.index = index; + this.currMinWeight = currMinWeight; + } + + /** + * Constructor for Node with default currMinWeight * @param identifier * @param index */ public Node(String identifier, int index) { this.identifier = identifier; this.index = index; + this.currMinWeight = Integer.MAX_VALUE; } /** @@ -28,38 +40,18 @@ public int getCurrMinWeight() { return currMinWeight; } - public void setCurrMinWeight(int currMinWeight) { - this.currMinWeight = currMinWeight; - } - /** * Getter for identifier * @return identifier */ - public boolean isVisited() { - return isVisited; - } - - /** - * Setter for isVisited - * @param isVisited - */ - public void setVisited(boolean isVisited) { - this.isVisited = isVisited; + public String getIdentifier() { + return identifier; } - /** - * Getter for identifier - * @return identifier - */ public int getIndex() { return index; } - public void setIndex(int index) { - this.index = index; - } - @Override public String toString() { return "Node{" + "identifier='" + identifier + '\'' + ", index=" + index + '}'; diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java index 6466b402..9b59dce0 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java @@ -11,8 +11,9 @@ * outgoing edge adjacent to any node in the MST (ensure the other end of the node is not already in the MST). * Repeat until S contains all nodes in the graph. S is the MST. * Actual implementation: - * No Edge class was implemented. Instead, the weights of the edges are stored in a 2D array adjacency matrix. - * A Node class is implemented to encapsulate a isVisited flag and the current minimum weight to reach the node. + * No Edge class was implemented. Instead, the weights of the edges are stored in a 2D array adjacency matrix. An + * adjacency list may be used instead + * A Node class is implemented to encapsulate the current minimum weight to reach the node. */ public class Prim { public static int[][] getPrimsMST(Node[] nodes, int[][] adjacencyMatrix) { @@ -27,6 +28,9 @@ public static int[][] getPrimsMST(Node[] nodes, int[][] adjacencyMatrix) { int[] parent = new int[nodes.length]; // To track the parent node of each node in the MST Arrays.fill(parent, -1); // Initialize parent array with -1, indicating no parent + boolean[] visited = new boolean[nodes.length]; // To track visited nodes + Arrays.fill(visited, false); // Initialize visited array with false, indicating not visited + // Initialize the MST matrix to represent no edges with Integer.MAX_VALUE and 0 for self loops for (int i = 0; i < nodes.length; i++) { for (int j = 0; j < nodes.length; j++) { @@ -34,27 +38,28 @@ public static int[][] getPrimsMST(Node[] nodes, int[][] adjacencyMatrix) { } } - // Initialize all nodes' currMinWeight to infinity, except the first node - for (Node node : nodes) { - node.setCurrMinWeight(Integer.MAX_VALUE); - pq.add(node); - } + // Add all nodes to the priority queue, with each node's curr min weight already set to Integer.MAX_VALUE + pq.addAll(Arrays.asList(nodes)); while (!pq.isEmpty()) { Node current = pq.poll(); - current.setVisited(true); int currentIndex = current.getIndex(); + if (visited[currentIndex]) { // Skip if node is already visited + continue; + } + + visited[currentIndex] = true; + for (int i = 0; i < nodes.length; i++) { - if (adjacencyMatrix[currentIndex][i] != Integer.MAX_VALUE && !nodes[i].isVisited()) { + if (adjacencyMatrix[currentIndex][i] != Integer.MAX_VALUE && !visited[nodes[i].getIndex()]) { int weight = adjacencyMatrix[currentIndex][i]; if (weight < nodes[i].getCurrMinWeight()) { - pq.remove(nodes[i]); - nodes[i].setCurrMinWeight(weight); - pq.add(nodes[i]); + Node newNode = new Node(nodes[i].getIdentifier(), nodes[i].getIndex(), weight); parent[i] = currentIndex; // Set current node as parent of adjacent node + pq.add(newNode); } } } diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/README.md b/src/main/java/algorithms/minimumSpanningTree/prims/README.md index f99d3025..50062a5b 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/README.md +++ b/src/main/java/algorithms/minimumSpanningTree/prims/README.md @@ -3,11 +3,44 @@ ## Background Prim's Algorithm is a greedy algorithm that finds the minimum spanning tree of a graph by starting from an -arbitrary node (vertex) and adding the edge with the minimum weight that connects the current tree to a new node, adding -the node to the current tree, until all nodes are included in the tree. +arbitrary node (vertex) and adding the edge, with the minimum weight that connects the current tree to an unexplored +node, and the unexplored node to the current tree, until all nodes are included in the tree. + +### Implementation Details + +A priority queue (binary heap) is utilised to keep track of the minimum weight edge that connects the current tree to an +unexplored node. In an ideal scenario, the minimum weight edge to each node in the priority queue should be updated each +time a lighter edge is found to maintain a single unique node in the priority queue. This means that a decrease key +operation is required. However, we know that the decrease key operation of a binary heap implementation of a priority +queue will take O(V) time, which will result in a larger time complexity for the entire algorithm compared to using only +O(log V) operations for each edge. + +Hence, in our implementation, to avoid the use of a decrease key operation, we will simply insert duplicate nodes with +their new minimum weight edge, which will take O(log E) = O(log V) given an upper bound of E = V^2, into the queue, +while leaving the old node in the queue. Additionally, we will track if a node has already been added into the MST to +avoid adding duplicate nodes. + +Note that a priority queue is an abstract data type that can be implemented using different data structures. In this +implementation, the default Java `PriorityQueue` is used, which is a binary heap. By implementing the priority queue +with an AVL tree, a decrease key operation that has a time complexity of O(log V) can also be achieved. ## Complexity Analysis +**Time Complexity:** +- O(V^2 log V) for the basic version with an adjacency matrix, where V is the number of vertices. +- O(E log V) with a binary heap and adjacency list, where V and E is the number of vertices and edges +respectively. + +**Space Complexity:** +- O(V^2) for the adjacency matrix representation. +- O(V + E) for the adjacency list representation. + ## Notes -### Difference between Prim's Algorithm and Dijkstra's Algorithm \ No newline at end of file +### Difference between Prim's Algorithm and Dijkstra's Algorithm + +| | Prim's Algorithm | Dijkstra's Algorithm | +|-------------------------------------|---------------------------------------------------------------------------------|----------------------------------------------------------| +| Purpose | Finds MST - minimum sum of edge weights that includes all vertices in the graph | Finds shortest path from a single source to all vertices | +| Property Compared in Priority Queue | Minimum weight of incoming edge to a vertex | Minimum distance from source vertex to current vertex | + diff --git a/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java b/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java index 36830e82..f54ddbfa 100644 --- a/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java +++ b/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java @@ -9,7 +9,11 @@ public class PrimsTest { @Test public void test_simpleGraph() { // Graph setup (Adjacency Matrix) - // A -1- B -1- C + // B + // / \ + // 1 1 + // / \ + // A - 1 - C int[][] adjacencyMatrix = { {0, 1, 1}, // A: A-B, A-C {1, 0, 1}, // B: B-A, B-C @@ -28,9 +32,9 @@ public void test_simpleGraph() { // Expected MST // A -1- B -1- C int[][] expectedMST = { - {0, 1, 1}, // A: A-B, A-C - {1, 0, Integer.MAX_VALUE}, // B: B-A - {1, Integer.MAX_VALUE, 0} // C: C-A + {0, 1, Integer.MAX_VALUE}, // A: A-B + {1, 0, 1}, // B: B-A, B-C + {Integer.MAX_VALUE, 1, 0} // C: C-B }; // Assertion @@ -42,18 +46,18 @@ public void test_complexGraph() { // Graph setup // A // / | \ - // 1 4 2 + // 1 4 3 /// | \ //B --3-- D // \ | / - // 2 4 3 + // 2 4 1 // \|/ // C int[][] adjacencyMatrix = { - {0, 1, 4, 2}, // A: A-B, A-C, A-D + {0, 1, 4, 3}, // A: A-B, A-C, A-D {1, 0, 2, 3}, // B: B-A, B-C, B-D - {4, 2, 0, 3}, // C: C-A, C-B, C-D - {2, 3, 3, 0} // D: D-A, D-B, D-C + {4, 2, 0, 1}, // C: C-A, C-B, C-D + {3, 3, 1, 0} // D: D-A, D-B, D-C }; Node[] nodes = { @@ -69,10 +73,10 @@ public void test_complexGraph() { // Expected MST // Based on the graph, assuming the MST is correctly computed int[][] expectedMST = { - {0, 1, Integer.MAX_VALUE, 2}, // A: A-B, A-D + {0, 1, Integer.MAX_VALUE, Integer.MAX_VALUE}, // A: A-B {1, 0, 2, Integer.MAX_VALUE}, // B: B-A, B-C - {Integer.MAX_VALUE, 2, 0, Integer.MAX_VALUE}, // C: C-B - {2, Integer.MAX_VALUE, Integer.MAX_VALUE, 0} // D: D-A + {Integer.MAX_VALUE, 2, 0, 1}, // C: C-B, C-D + {Integer.MAX_VALUE, Integer.MAX_VALUE, 1, 0} // D: D-C }; // Assertion From 35550ed884f51e9504b09e0308120d2c1060bbd4 Mon Sep 17 00:00:00 2001 From: junnengsoo Date: Wed, 27 Mar 2024 19:35:22 +0800 Subject: [PATCH 28/51] Add Kruskal's implementation and tests less README --- .../algorithms/minimumSpanningTree/README.md | 2 +- .../kruskal/DisjointSet.java | 59 +++++++++++++ .../minimumSpanningTree/kruskal/Edge.java | 36 ++++++++ .../minimumSpanningTree/kruskal/Kruskal.java | 61 ++++++++++++++ .../minimumSpanningTree/kruskal/Node.java | 38 +++++++++ .../{prims => prim}/Node.java | 2 +- .../{prims => prim}/Prim.java | 7 +- .../{prims => prim}/README.md | 0 .../kruskal/KruskalTest.java | 84 +++++++++++++++++++ .../PrimsTest.java => prim/PrimTest.java} | 4 +- 10 files changed, 283 insertions(+), 10 deletions(-) create mode 100644 src/main/java/algorithms/minimumSpanningTree/kruskal/DisjointSet.java create mode 100644 src/main/java/algorithms/minimumSpanningTree/kruskal/Edge.java create mode 100644 src/main/java/algorithms/minimumSpanningTree/kruskal/Kruskal.java create mode 100644 src/main/java/algorithms/minimumSpanningTree/kruskal/Node.java rename src/main/java/algorithms/minimumSpanningTree/{prims => prim}/Node.java (96%) rename src/main/java/algorithms/minimumSpanningTree/{prims => prim}/Prim.java (93%) rename src/main/java/algorithms/minimumSpanningTree/{prims => prim}/README.md (100%) create mode 100644 src/test/java/algorithms/minimumSpanningTree/kruskal/KruskalTest.java rename src/test/java/algorithms/minimumSpanningTree/{prims/PrimsTest.java => prim/PrimTest.java} (96%) diff --git a/src/main/java/algorithms/minimumSpanningTree/README.md b/src/main/java/algorithms/minimumSpanningTree/README.md index e173d723..994f0d77 100644 --- a/src/main/java/algorithms/minimumSpanningTree/README.md +++ b/src/main/java/algorithms/minimumSpanningTree/README.md @@ -9,7 +9,7 @@ is a spanning tree with the minimum possible total edge weight. ## Prim's Algorithm We will discuss more implementation-specific details and complexity analysis in the respective folders. In short, -1. [Prim's Algorithm](prims) is a greedy algorithm that finds the minimum spanning tree of a graph by starting from an +1. [Prim's Algorithm](prim) is a greedy algorithm that finds the minimum spanning tree of a graph by starting from an arbitrary node (vertex) and adding the edge with the minimum weight that connects the current tree to a new node, adding the node to the current tree, until all nodes are included in the tree. diff --git a/src/main/java/algorithms/minimumSpanningTree/kruskal/DisjointSet.java b/src/main/java/algorithms/minimumSpanningTree/kruskal/DisjointSet.java new file mode 100644 index 00000000..7d5d7b01 --- /dev/null +++ b/src/main/java/algorithms/minimumSpanningTree/kruskal/DisjointSet.java @@ -0,0 +1,59 @@ +package algorithms.minimumSpanningTree.kruskal; + +import java.util.HashMap; +import java.util.Map; + +/** + * Implementation of quick-find structure; Turns a list of objects into a data structure that supports union operations + */ +public class DisjointSet { + private final Map identifier; + + /** + * Constructor to initialize Disjoint Set with a known list of listOfNodes. + * @param listOfNodes + */ + public DisjointSet(Node[] listOfNodes) { + identifier = new HashMap<>(); + for (Node currNode : listOfNodes) { + // Component identifier is the same as the node's identifier + identifier.put(currNode, currNode.getIdentifier()); + } + } + + /** + * Checks if object a and object b are in the same component. + * @param a + * @param b + * @return a boolean value + */ + public boolean find(Node a, Node b) { + if (!identifier.containsKey(a) || !identifier.containsKey(b)) { // key(s) does not even exist + return false; + } + return identifier.get(a).equals(identifier.get(b)); + } + + /** + * Merge the components of object a and object b. + * @param a + * @param b + */ + public void union(Node a, Node b) { + if (!identifier.containsKey(a) || !identifier.containsKey(b)) { // key(s) does not even exist; do nothing + return; + } + + if (identifier.get(a).equals(identifier.get(b))) { // already same; do nothing + return; + } + + String compOfA = identifier.get(a); + String compOfB = identifier.get(b); + for (Node obj : identifier.keySet()) { + if (identifier.get(obj).equals(compOfA)) { + identifier.put(obj, compOfB); + } + } + } +} diff --git a/src/main/java/algorithms/minimumSpanningTree/kruskal/Edge.java b/src/main/java/algorithms/minimumSpanningTree/kruskal/Edge.java new file mode 100644 index 00000000..3b27d238 --- /dev/null +++ b/src/main/java/algorithms/minimumSpanningTree/kruskal/Edge.java @@ -0,0 +1,36 @@ +package algorithms.minimumSpanningTree.kruskal; + +/** + * Edge class to represent an edge in the graph + */ +public class Edge implements Comparable { + private final Node source; + private final Node destination; + private final int weight; + + /** + * Constructor for Edge + */ + public Edge(Node source, Node destination, int weight) { + this.source = source; + this.destination = destination; + this.weight = weight; + } + + public int getWeight() { + return weight; + } + + public Node getSource() { + return source; + } + + public Node getDestination() { + return destination; + } + + @Override + public int compareTo(Edge other) { + return Integer.compare(this.weight, other.weight); + } +} diff --git a/src/main/java/algorithms/minimumSpanningTree/kruskal/Kruskal.java b/src/main/java/algorithms/minimumSpanningTree/kruskal/Kruskal.java new file mode 100644 index 00000000..0fc83125 --- /dev/null +++ b/src/main/java/algorithms/minimumSpanningTree/kruskal/Kruskal.java @@ -0,0 +1,61 @@ +package algorithms.minimumSpanningTree.kruskal; + +import java.util.ArrayList; +import java.util.List; + +/** + * Implementation of Prim's Algorithm to find MSTs + * Idea: + * Starting from any source (this will be the first node to be in the MST), pick the lightest outgoing edge, and + * include the node at the other end as part of a set of nodes S. Now repeatedly do the above by picking the lightest + * outgoing edge adjacent to any node in the MST (ensure the other end of the node is not already in the MST). + * Repeat until S contains all nodes in the graph. S is the MST. + * Actual implementation: + * No Edge class was implemented. Instead, the weights of the edges are stored in a 2D array adjacency matrix. An + * adjacency list may be used instead + * A Node class is implemented to encapsulate the current minimum weight to reach the node. + */ +public class Kruskal { + public static int[][] getKruskalMST(Node[] nodes, int[][] adjacencyMatrix) { + int numOfNodes = nodes.length; + List edges = new ArrayList<>(); + + // Convert adjacency matrix to list of edges + for (int i = 0; i < numOfNodes; i++) { + for (int j = i + 1; j < numOfNodes; j++) { + if (adjacencyMatrix[i][j] != Integer.MAX_VALUE) { + edges.add(new Edge(nodes[i], nodes[j], adjacencyMatrix[i][j])); + } + } + } + + // Sort edges by weight + edges.sort(Edge::compareTo); + + // Initialize Disjoint Set for vertex tracking + DisjointSet ds = new DisjointSet(nodes); + + int[][] mstMatrix = new int[numOfNodes][numOfNodes]; + + // Initialize the MST matrix to represent no edges with Integer.MAX_VALUE and 0 for self loops + for (int i = 0; i < nodes.length; i++) { + for (int j = 0; j < nodes.length; j++) { + mstMatrix[i][j] = (i == j) ? 0 : Integer.MAX_VALUE; + } + } + + // Process edges to build MST + for (Edge edge : edges) { + Node source = edge.getSource(); + Node destination = edge.getDestination(); + if (!ds.find(source, destination)) { + mstMatrix[source.getIndex()][destination.getIndex()] = edge.getWeight(); + mstMatrix[destination.getIndex()][source.getIndex()] = edge.getWeight(); + ds.union(source, destination); + } + } + + return mstMatrix; + } +} + diff --git a/src/main/java/algorithms/minimumSpanningTree/kruskal/Node.java b/src/main/java/algorithms/minimumSpanningTree/kruskal/Node.java new file mode 100644 index 00000000..ca6ae0e3 --- /dev/null +++ b/src/main/java/algorithms/minimumSpanningTree/kruskal/Node.java @@ -0,0 +1,38 @@ +package algorithms.minimumSpanningTree.kruskal; + +/** + * Node class to represent a node in the graph + * Note: In our Node class, we do not allow the currMinWeight to be updated after initialization to prevent any + * reference issues in the PriorityQueue. + */ +public class Node { + private final int index; // Index of this node in the adjacency matrix + private final String identifier; + + /** + * Constructor for Node + * @param identifier + * @param index + */ + public Node(String identifier, int index) { + this.identifier = identifier; + this.index = index; + } + + /** + * Getter for identifier + * @return identifier + */ + public String getIdentifier() { + return identifier; + } + + public int getIndex() { + return index; + } + + @Override + public String toString() { + return "Node{" + "identifier='" + identifier + '\'' + ", index=" + index + '}'; + } +} diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java b/src/main/java/algorithms/minimumSpanningTree/prim/Node.java similarity index 96% rename from src/main/java/algorithms/minimumSpanningTree/prims/Node.java rename to src/main/java/algorithms/minimumSpanningTree/prim/Node.java index fb465f00..c06a960d 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java +++ b/src/main/java/algorithms/minimumSpanningTree/prim/Node.java @@ -1,4 +1,4 @@ -package algorithms.minimumSpanningTree.prims; +package algorithms.minimumSpanningTree.prim; /** * Node class to represent a node in the graph diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java b/src/main/java/algorithms/minimumSpanningTree/prim/Prim.java similarity index 93% rename from src/main/java/algorithms/minimumSpanningTree/prims/Prim.java rename to src/main/java/algorithms/minimumSpanningTree/prim/Prim.java index 9b59dce0..f53d382e 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java +++ b/src/main/java/algorithms/minimumSpanningTree/prim/Prim.java @@ -1,4 +1,4 @@ -package algorithms.minimumSpanningTree.prims; +package algorithms.minimumSpanningTree.prim; import java.util.Arrays; import java.util.PriorityQueue; @@ -20,11 +20,6 @@ public static int[][] getPrimsMST(Node[] nodes, int[][] adjacencyMatrix) { PriorityQueue pq = new PriorityQueue<>((a, b) -> a.getCurrMinWeight() - b.getCurrMinWeight()); int[][] mstMatrix = new int[nodes.length][nodes.length]; // MST adjacency matrix - // Initialize mstMatrix with all edges set to Integer.MAX_VALUE - for (int[] row : mstMatrix) { - Arrays.fill(row, Integer.MAX_VALUE); - } - int[] parent = new int[nodes.length]; // To track the parent node of each node in the MST Arrays.fill(parent, -1); // Initialize parent array with -1, indicating no parent diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/README.md b/src/main/java/algorithms/minimumSpanningTree/prim/README.md similarity index 100% rename from src/main/java/algorithms/minimumSpanningTree/prims/README.md rename to src/main/java/algorithms/minimumSpanningTree/prim/README.md diff --git a/src/test/java/algorithms/minimumSpanningTree/kruskal/KruskalTest.java b/src/test/java/algorithms/minimumSpanningTree/kruskal/KruskalTest.java new file mode 100644 index 00000000..76efc48c --- /dev/null +++ b/src/test/java/algorithms/minimumSpanningTree/kruskal/KruskalTest.java @@ -0,0 +1,84 @@ +package algorithms.minimumSpanningTree.kruskal; + +import static org.junit.Assert.assertArrayEquals; + +import org.junit.Test; + +public class KruskalTest { + @Test + public void test_simpleGraph() { + // Graph setup (Adjacency Matrix) + // B + // / \ + // 1 1 + // / \ + // A - 1 - C + int[][] adjacencyMatrix = { + {0, 1, 1}, // A: A-B, A-C + {1, 0, 1}, // B: B-A, B-C + {1, 1, 0} // C: C-A, C-B + }; + + Node[] nodes = { + new Node("A", 0), + new Node("B", 1), + new Node("C", 2) + }; + + // Run Kruskal's algorithm + int[][] actualMST = Kruskal.getKruskalMST(nodes, adjacencyMatrix); + + // Expected MST + // A -1- B -1- C + int[][] expectedMST = { + {0, 1, 1}, // A: A-B, A-C + {1, 0, Integer.MAX_VALUE}, // B: B-A + {1, Integer.MAX_VALUE, 0} // C: C-A + }; + + // Assertion + assertArrayEquals(expectedMST, actualMST); + } + + @Test + public void test_complexGraph() { + // Graph setup + // A + // / | \ + // 1 4 3 + /// | \ + //B --3-- D + // \ | / + // 2 4 1 + // \|/ + // C + int[][] adjacencyMatrix = { + {0, 1, 4, 3}, // A: A-B, A-C, A-D + {1, 0, 2, 3}, // B: B-A, B-C, B-D + {4, 2, 0, 1}, // C: C-A, C-B, C-D + {3, 3, 1, 0} // D: D-A, D-B, D-C + }; + + Node[] nodes = { + new Node("A", 0), + new Node("B", 1), + new Node("C", 2), + new Node("D", 3) + }; + + // Run Prim's algorithm + int[][] actualMST = Kruskal.getKruskalMST(nodes, adjacencyMatrix); + + // Expected MST + // Based on the graph, assuming the MST is correctly computed + int[][] expectedMST = { + {0, 1, Integer.MAX_VALUE, Integer.MAX_VALUE}, // A: A-B + {1, 0, 2, Integer.MAX_VALUE}, // B: B-A, B-C + {Integer.MAX_VALUE, 2, 0, 1}, // C: C-B, C-D + {Integer.MAX_VALUE, Integer.MAX_VALUE, 1, 0} // D: D-C + }; + + // Assertion + assertArrayEquals(expectedMST, actualMST); + } +} diff --git a/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java b/src/test/java/algorithms/minimumSpanningTree/prim/PrimTest.java similarity index 96% rename from src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java rename to src/test/java/algorithms/minimumSpanningTree/prim/PrimTest.java index f54ddbfa..6ecc531d 100644 --- a/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java +++ b/src/test/java/algorithms/minimumSpanningTree/prim/PrimTest.java @@ -1,10 +1,10 @@ -package algorithms.minimumSpanningTree.prims; +package algorithms.minimumSpanningTree.prim; import static org.junit.Assert.assertArrayEquals; import org.junit.Test; -public class PrimsTest { +public class PrimTest { @Test public void test_simpleGraph() { From 1fe6a231f200dbcdfee8d56bb564c47fc6239a69 Mon Sep 17 00:00:00 2001 From: kaitinghh <114789615+kaitinghh@users.noreply.github.com> Date: Fri, 29 Mar 2024 12:22:25 +0800 Subject: [PATCH 29/51] style: fix checkstyle errors --- .../RangeTreeNode.java | 172 ++--- .../oneDim/OrthogonalRangeSearching.java | 685 +++++++++--------- .../orthogonalRangeSearching/oneDim/README.md | 6 +- .../twoDim/OrthogonalRangeSearching.java | 100 +-- .../oneDim/OrthogonalRangeSearchingTest.java | 97 +-- .../twoDim/OrthogonalRangeSearchingTest.java | 45 +- 6 files changed, 565 insertions(+), 540 deletions(-) diff --git a/src/main/java/algorithms/orthogonalRangeSearching/RangeTreeNode.java b/src/main/java/algorithms/orthogonalRangeSearching/RangeTreeNode.java index a55b9b5f..2a52b75d 100644 --- a/src/main/java/algorithms/orthogonalRangeSearching/RangeTreeNode.java +++ b/src/main/java/algorithms/orthogonalRangeSearching/RangeTreeNode.java @@ -1,86 +1,96 @@ package algorithms.orthogonalRangeSearching; +/** + * This class is the node class for building a range tree. + * @param Generic type of the node class + */ public class RangeTreeNode { - T val; - int height; - RangeTreeNode left = null; - RangeTreeNode right = null; - RangeTreeNode parent = null; - RangeTreeNode yTree = null; - - public RangeTreeNode(T val) { - this.val = val; - } - - public RangeTreeNode(T val, RangeTreeNode left, RangeTreeNode right) { - this.val = val; - this.left = left; - this.right = right; - } - - public T getVal() { - return this.val; - } - - public int getHeight() { - return this.height; - } - - public RangeTreeNode getLeft() { - return this.left; - } - - public RangeTreeNode getRight() { - return this.right; - } - - public RangeTreeNode getParent() { - return this.parent; - } - - public RangeTreeNode getYTree() { - return this.yTree; - } - - public void setVal(T val) { - this.val = val; - } - - public void setLeft(RangeTreeNode left) { - this.left = left; - } - - public void setRight(RangeTreeNode right) { - this.right = right; - } - - public void setParent(RangeTreeNode parent) { - this.parent = parent; - } - - public void setHeight(int height) { - this.height = height; - } - - public void setYTree(RangeTreeNode yTree) { - this.yTree = yTree; - } - - @Override - public boolean equals(Object other) { - if (other == this) { - return true; - } - if (!(other instanceof RangeTreeNode)) { - return false; - } - RangeTreeNode node = (RangeTreeNode) other; - return this.val == node.val; - } - - @Override - public String toString() { - return String.valueOf(this.val); - } + private T val; + private int height; + private RangeTreeNode left = null; + private RangeTreeNode right = null; + private RangeTreeNode parent = null; + private RangeTreeNode yTree = null; + + public RangeTreeNode(T val) { + this.val = val; + } + + /** + * Constructor for range tree node + * @param val value of node + * @param left left child of node + * @param right right child of node + */ + public RangeTreeNode(T val, RangeTreeNode left, RangeTreeNode right) { + this.val = val; + this.left = left; + this.right = right; + } + + public T getVal() { + return this.val; + } + + public int getHeight() { + return this.height; + } + + public RangeTreeNode getLeft() { + return this.left; + } + + public RangeTreeNode getRight() { + return this.right; + } + + public RangeTreeNode getParent() { + return this.parent; + } + + public RangeTreeNode getYTree() { + return this.yTree; + } + + public void setVal(T val) { + this.val = val; + } + + public void setLeft(RangeTreeNode left) { + this.left = left; + } + + public void setRight(RangeTreeNode right) { + this.right = right; + } + + public void setParent(RangeTreeNode parent) { + this.parent = parent; + } + + public void setHeight(int height) { + this.height = height; + } + + public void setYTree(RangeTreeNode yTree) { + this.yTree = yTree; + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if (!(other instanceof RangeTreeNode)) { + return false; + } + RangeTreeNode node = (RangeTreeNode) other; + return this.val == node.val; + } + + @Override + public String toString() { + return String.valueOf(this.val); + } } diff --git a/src/main/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearching.java b/src/main/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearching.java index 489f0b31..bc5892a2 100644 --- a/src/main/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearching.java +++ b/src/main/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearching.java @@ -1,391 +1,398 @@ package algorithms.orthogonalRangeSearching.oneDim; -import algorithms.orthogonalRangeSearching.RangeTreeNode; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.Queue; +import algorithms.orthogonalRangeSearching.RangeTreeNode; + +/** + * This class performs 1 dimensional orthogonal range searching. + */ public class OrthogonalRangeSearching { - /** - * Builds a Range Tree from an array of integers. - * - * @param inputs The array of integers. - * @param start The starting index of the input array. - * @param end The ending index of the input array. - * @return The root node of the constructed Range Tree. - */ - public static RangeTreeNode buildTree(int[] inputs, int start, int end) { - int mid = (end + start) / 2; - Arrays.sort(inputs); + /** + * Builds a Range Tree from an array of integers. + * + * @param inputs The array of integers. + * @param start The starting index of the input array. + * @param end The ending index of the input array. + * @return The root node of the constructed Range Tree. + */ + public static RangeTreeNode buildTree(int[] inputs, int start, int end) { + int mid = (end + start) / 2; + Arrays.sort(inputs); - if (start > end) { - return null; - } else if (start == end) { - return new RangeTreeNode<>(inputs[start]); - } else { - return new RangeTreeNode<>(inputs[mid], buildTree(inputs, start, mid), - buildTree(inputs, mid + 1, end)); + if (start > end) { + return null; + } else if (start == end) { + return new RangeTreeNode<>(inputs[start]); + } else { + return new RangeTreeNode<>(inputs[mid], buildTree(inputs, start, mid), + buildTree(inputs, mid + 1, end)); + } } - } - /** - * Finds the split node in the Range Tree based on a given range. - * - * @param root The root node of the Range Tree. - * @param low The lower bound of the range. - * @param high The upper bound of the range. - * @return The split node in the Range Tree. - */ - public static RangeTreeNode findSplit(RangeTreeNode root, int low, int high) { - RangeTreeNode v = root; + /** + * Finds the split node in the Range Tree based on a given range. + * + * @param root The root node of the Range Tree. + * @param low The lower bound of the range. + * @param high The upper bound of the range. + * @return The split node in the Range Tree. + */ + public static RangeTreeNode findSplit(RangeTreeNode root, int low, int high) { + RangeTreeNode v = root; - while (true) { - if (v == null) { - return null; - } else { - if (high <= v.getVal()) { - if (isLeaf(v)) { - break; - } - v = v.getLeft(); - } else if (low > v.getVal()) { - v = v.getRight(); - } else { - break; + while (true) { + if (v == null) { + return null; + } else { + if (high <= v.getVal()) { + if (isLeaf(v)) { + break; + } + v = v.getLeft(); + } else if (low > v.getVal()) { + v = v.getRight(); + } else { + break; + } + } } - } + return v; } - return v; - } - /** - * Performs a recursive traversal of the Range Tree and adds leaf node values to the result list. - * - * @param v The current node being processed during traversal. - * @param result The list to store the values of leaf nodes encountered during traversal. - */ - public static void allLeafTraversal(RangeTreeNode v, List result) { - if (v != null) { - if (v.getLeft() != null) { - allLeafTraversal(v.getLeft(), result); - } - if (isLeaf(v)) { - result.add(v.getVal()); - } - if (v.getRight() != null) { - allLeafTraversal(v.getRight(), result); - } + /** + * Performs a recursive traversal of the Range Tree and adds leaf node values to the result list. + * + * @param v The current node being processed during traversal. + * @param result The list to store the values of leaf nodes encountered during traversal. + */ + public static void allLeafTraversal(RangeTreeNode v, List result) { + if (v != null) { + if (v.getLeft() != null) { + allLeafTraversal(v.getLeft(), result); + } + if (isLeaf(v)) { + result.add(v.getVal()); + } + if (v.getRight() != null) { + allLeafTraversal(v.getRight(), result); + } + } } - } - /** - * Performs a left traversal of the Range Tree to find nodes within a specified range. - * - * @param v The current node being processed. - * @param low The lower bound of the range. - * @param result A list to store the results of the traversal. - */ - public static void leftTraversal(RangeTreeNode v, int low, List result) { - if (v != null) { - if (isLeaf(v)) { - result.add(v.getVal()); - } else { - if (low <= v.getVal()) { - leftTraversal(v.getLeft(), low, result); - allLeafTraversal(v.getRight(), result); - } else { // definitely a qualifying leaf has to exist - leftTraversal(v.getRight(), low, result); + /** + * Performs a left traversal of the Range Tree to find nodes within a specified range. + * + * @param v The current node being processed. + * @param low The lower bound of the range. + * @param result A list to store the results of the traversal. + */ + public static void leftTraversal(RangeTreeNode v, int low, List result) { + if (v != null) { + if (isLeaf(v)) { + result.add(v.getVal()); + } else { + if (low <= v.getVal()) { + leftTraversal(v.getLeft(), low, result); + allLeafTraversal(v.getRight(), result); + } else { // definitely a qualifying leaf has to exist + leftTraversal(v.getRight(), low, result); + } + } } - } } - } - /** - * Performs a right traversal of the Range Tree to find nodes within a specified range. - * - * @param v The current node being processed. - * @param high The upper bound of the range. - * @param result A list to store the results of the traversal. - */ - public static void rightTraversal(RangeTreeNode v, int high, List result) { - if (v != null) { - if (isLeaf(v) && v.getVal() <= high) { // leaf, need extra check - result.add(v.getVal()); - } else { - if (high > v.getVal()) { - allLeafTraversal(v.getLeft(), result); - rightTraversal(v.getRight(), high, result); - } else { // a qualifying leaf might or might not exist, we are just exploring - rightTraversal(v.getLeft(), high, result); + /** + * Performs a right traversal of the Range Tree to find nodes within a specified range. + * + * @param v The current node being processed. + * @param high The upper bound of the range. + * @param result A list to store the results of the traversal. + */ + public static void rightTraversal(RangeTreeNode v, int high, List result) { + if (v != null) { + if (isLeaf(v) && v.getVal() <= high) { // leaf, need extra check + result.add(v.getVal()); + } else { + if (high > v.getVal()) { + allLeafTraversal(v.getLeft(), result); + rightTraversal(v.getRight(), high, result); + } else { // a qualifying leaf might or might not exist, we are just exploring + rightTraversal(v.getLeft(), high, result); + } + } } - } } - } - /** - * Searches for elements within a specified range in the Range Tree. - * - * @param tree The root node of the Range Tree. - * @param low The lower bound of the range. - * @param high The upper bound of the range. - * @return An array of elements within the specified range. - */ - public static Object[] search(RangeTreeNode tree, int low, int high) { - RangeTreeNode splitNode = OrthogonalRangeSearching.findSplit(tree, low, high); - ArrayList result = new ArrayList<>(); - if (splitNode != null) { - if (isLeaf(splitNode) && splitNode.getVal() >= low - && splitNode.getVal() <= high) { - result.add(splitNode.getVal()); - } - leftTraversal(splitNode.getLeft(), low, result); - rightTraversal(splitNode.getRight(), high, result); + /** + * Searches for elements within a specified range in the Range Tree. + * + * @param tree The root node of the Range Tree. + * @param low The lower bound of the range. + * @param high The upper bound of the range. + * @return An array of elements within the specified range. + */ + public static Object[] search(RangeTreeNode tree, int low, int high) { + RangeTreeNode splitNode = OrthogonalRangeSearching.findSplit(tree, low, high); + ArrayList result = new ArrayList<>(); + if (splitNode != null) { + if (isLeaf(splitNode) && splitNode.getVal() >= low + && splitNode.getVal() <= high) { + result.add(splitNode.getVal()); + } + leftTraversal(splitNode.getLeft(), low, result); + rightTraversal(splitNode.getRight(), high, result); + } + return result.toArray(); } - return result.toArray(); - } - private static boolean isLeaf(RangeTreeNode node) { - return node.getLeft() == null && node.getRight() == null; - } + private static boolean isLeaf(RangeTreeNode node) { + return node.getLeft() == null && node.getRight() == null; + } - // FUNCTIONS FROM HERE ONWARDS ARE DESIGNED TO SUPPORT DYNAMIC UPDATES. + // FUNCTIONS FROM HERE ONWARDS ARE DESIGNED TO SUPPORT DYNAMIC UPDATES. - /** - * Configures the height and parent nodes for the nodes in the Range Tree. - * Note that this is only needed if we want to support dynamic updating of the range tree. - * - * @param node The root node of the Range Tree. - */ - public static void configureTree(RangeTreeNode node) { - if (node.getLeft() == null && node.getRight() == null) { - node.setHeight(0); - } else if (node.getLeft() == null) { - configureTree(node.getRight()); - node.setHeight(node.getRight().getHeight() + 1); - node.getRight().setParent(node); - } else if (node.getRight() == null) { - configureTree(node.getLeft()); - node.setHeight(node.getLeft().getHeight() + 1); - node.getLeft().setParent(node); - } else { - configureTree(node.getLeft()); - configureTree(node.getRight()); - node.setHeight(Math.max(node.getLeft().getHeight(), node.getRight().getHeight()) + 1); - node.getLeft().setParent(node); - node.getRight().setParent(node); + /** + * Configures the height and parent nodes for the nodes in the Range Tree. + * Note that this is only needed if we want to support dynamic updating of the range tree. + * + * @param node The root node of the Range Tree. + */ + public static void configureTree(RangeTreeNode node) { + if (node.getLeft() == null && node.getRight() == null) { + node.setHeight(0); + } else if (node.getLeft() == null) { + configureTree(node.getRight()); + node.setHeight(node.getRight().getHeight() + 1); + node.getRight().setParent(node); + } else if (node.getRight() == null) { + configureTree(node.getLeft()); + node.setHeight(node.getLeft().getHeight() + 1); + node.getLeft().setParent(node); + } else { + configureTree(node.getLeft()); + configureTree(node.getRight()); + node.setHeight(Math.max(node.getLeft().getHeight(), node.getRight().getHeight()) + 1); + node.getLeft().setParent(node); + node.getRight().setParent(node); + } } - } - /** - * Inserts a new element into the Range Tree while maintaining balance. - * - * @param node The root node of the Range Tree. - * @param val The value to be inserted. - * @return The root node of the updated Range Tree. - */ - public static RangeTreeNode insert(RangeTreeNode node, int val) { - if (val < node.getVal()) { - if (node.getLeft() != null) { - node.setLeft(insert(node.getLeft(), val)); - } else { - node.setLeft(new RangeTreeNode(val)); - node.getLeft().setParent(node); - node.setRight(new RangeTreeNode(node.getVal())); - node.getRight().setParent(node); - node.setVal(val); - } - } else if (val > node.getVal()) { - if (node.getRight() != null) { - node.setRight(insert(node.getRight(), val)); - } else { - node.setLeft(new RangeTreeNode(node.getVal())); - node.getLeft().setParent(node); - node.setRight(new RangeTreeNode(val)); - node.getRight().setParent(node); - node.setVal(node.getVal()); - } - } else { - throw new RuntimeException("Duplicate key not supported!"); + /** + * Inserts a new element into the Range Tree while maintaining balance. + * + * @param node The root node of the Range Tree. + * @param val The value to be inserted. + * @return The root node of the updated Range Tree. + */ + public static RangeTreeNode insert(RangeTreeNode node, int val) { + if (val < node.getVal()) { + if (node.getLeft() != null) { + node.setLeft(insert(node.getLeft(), val)); + } else { + node.setLeft(new RangeTreeNode(val)); + node.getLeft().setParent(node); + node.setRight(new RangeTreeNode(node.getVal())); + node.getRight().setParent(node); + node.setVal(val); + } + } else if (val > node.getVal()) { + if (node.getRight() != null) { + node.setRight(insert(node.getRight(), val)); + } else { + node.setLeft(new RangeTreeNode(node.getVal())); + node.getLeft().setParent(node); + node.setRight(new RangeTreeNode(val)); + node.getRight().setParent(node); + node.setVal(node.getVal()); + } + } else { + throw new RuntimeException("Duplicate key not supported!"); + } + return rebalance(node); } - return rebalance(node); - } - /** - * Calculates and returns the height of the given Range Tree node. - * - * @param node The Range Tree node for which to calculate the height. - * @return The height of the node, or -1 if the node is null. - */ - private static int height(RangeTreeNode node) { - return node == null - ? -1 - : node.getHeight(); - } + /** + * Calculates and returns the height of the given Range Tree node. + * + * @param node The Range Tree node for which to calculate the height. + * @return The height of the node, or -1 if the node is null. + */ + private static int height(RangeTreeNode node) { + return node == null + ? -1 + : node.getHeight(); + } - /** - * Update height of node in range tree during rebalancing. - * @param node node whose height is to be updated - */ - private static void updateHeight(RangeTreeNode node) { - node.setHeight(1 + Math.max(height(node.getLeft()), height(node.getRight()))); - } + /** + * Update height of node in range tree during rebalancing. + * + * @param node node whose height is to be updated + */ + private static void updateHeight(RangeTreeNode node) { + node.setHeight(1 + Math.max(height(node.getLeft()), height(node.getRight()))); + } - /** - * Get balance factor to check if height-balanced property is violated. - * Note: negative value means tree is right heavy, - * positive value means tree is left heavy, - * 0 means tree is balanced in weight. - * @param node check balance factor of node - * @return int value representing the balance factor - */ - private static int getBalance(RangeTreeNode node) { - return node == null - ? 0 - : height(node.getLeft()) - height(node.getRight()); - } + /** + * Get balance factor to check if height-balanced property is violated. + * Note: negative value means tree is right heavy, + * positive value means tree is left heavy, + * 0 means tree is balanced in weight. + * + * @param node check balance factor of node + * @return int value representing the balance factor + */ + private static int getBalance(RangeTreeNode node) { + return node == null + ? 0 + : height(node.getLeft()) - height(node.getRight()); + } - /** - * Performs a right rotation on the specified node. - * Note that function should be called only if the node has a left child since it will be the new root. - * @param n node to perform right rotation on. - * @return the new root after rotation. - */ - private static RangeTreeNode rotateRight(RangeTreeNode n) { - RangeTreeNode newRoot = n.getLeft(); - RangeTreeNode newLeftSub = newRoot.getRight(); - newRoot.setRight(n); - n.setLeft(newLeftSub); + /** + * Performs a right rotation on the specified node. + * Note that function should be called only if the node has a left child since it will be the new root. + * + * @param n node to perform right rotation on. + * @return the new root after rotation. + */ + private static RangeTreeNode rotateRight(RangeTreeNode n) { + RangeTreeNode newRoot = n.getLeft(); + RangeTreeNode newLeftSub = newRoot.getRight(); + newRoot.setRight(n); + n.setLeft(newLeftSub); - newRoot.setParent(n.getParent()); - n.setParent(newRoot); + newRoot.setParent(n.getParent()); + n.setParent(newRoot); - updateHeight(n); - updateHeight(newRoot); - return newRoot; - } + updateHeight(n); + updateHeight(newRoot); + return newRoot; + } - /** - * Performs a left rotation on the specified node. - * Note that function should be called only if the node has a right child since it will be the new root. - * - * @param n node to perform left rotation on - * @return new root after rotation - */ - private static RangeTreeNode rotateLeft(RangeTreeNode n) { - RangeTreeNode newRoot = n.getRight(); // newRoot is the right subtree of the original root - RangeTreeNode newRightSub = newRoot.getLeft(); - newRoot.setLeft(n); - n.setRight(newRightSub); + /** + * Performs a left rotation on the specified node. + * Note that function should be called only if the node has a right child since it will be the new root. + * + * @param n node to perform left rotation on + * @return new root after rotation + */ + private static RangeTreeNode rotateLeft(RangeTreeNode n) { + RangeTreeNode newRoot = n.getRight(); // newRoot is the right subtree of the original root + RangeTreeNode newRightSub = newRoot.getLeft(); + newRoot.setLeft(n); + n.setRight(newRightSub); - newRoot.setParent(n.getParent()); - n.setParent(newRoot); + newRoot.setParent(n.getParent()); + n.setParent(newRoot); - updateHeight(n); - updateHeight(newRoot); - return newRoot; - } + updateHeight(n); + updateHeight(newRoot); + return newRoot; + } - /** - * Rebalances a node in the tree based on balance factor. - * - * @param n node to be rebalanced - * @return new root after rebalancing - */ - private static RangeTreeNode rebalance(RangeTreeNode n) { - updateHeight(n); - int balance = getBalance(n); - if (balance < -1) { // right-heavy case - RangeTreeNode rightChild = n.getRight(); - if (height(rightChild.getLeft()) > height(rightChild.getRight())) { - n.setRight(rotateRight(n.getRight())); - } - n = rotateLeft(n); - } else if (balance > 1) { // left-heavy case - RangeTreeNode leftChild = n.getLeft(); - if (height(leftChild.getRight()) > height(leftChild.getLeft())) { - n.setLeft(rotateLeft(n.getLeft())); - } - n = rotateRight(n); + /** + * Rebalances a node in the tree based on balance factor. + * + * @param n node to be rebalanced + * @return new root after rebalancing + */ + private static RangeTreeNode rebalance(RangeTreeNode n) { + updateHeight(n); + int balance = getBalance(n); + if (balance < -1) { // right-heavy case + RangeTreeNode rightChild = n.getRight(); + if (height(rightChild.getLeft()) > height(rightChild.getRight())) { + n.setRight(rotateRight(n.getRight())); + } + n = rotateLeft(n); + } else if (balance > 1) { // left-heavy case + RangeTreeNode leftChild = n.getLeft(); + if (height(leftChild.getRight()) > height(leftChild.getLeft())) { + n.setLeft(rotateLeft(n.getLeft())); + } + n = rotateRight(n); + } + return n; } - return n; - } - /** - * Deletes an element from the Range Tree while maintaining balance. - * - * @param node The root node of the Range Tree. - * @param val The value to be deleted. - * @return The root node of the updated Range Tree. - */ - public static RangeTreeNode delete(RangeTreeNode node, int val) { - RangeTreeNode leftChild = node.getLeft(); - RangeTreeNode rightChild = node.getRight(); + /** + * Deletes an element from the Range Tree while maintaining balance. + * + * @param node The root node of the Range Tree. + * @param val The value to be deleted. + * @return The root node of the updated Range Tree. + */ + public static RangeTreeNode delete(RangeTreeNode node, int val) { + RangeTreeNode leftChild = node.getLeft(); + RangeTreeNode rightChild = node.getRight(); - if (leftChild.getLeft() == null && leftChild.getRight() == null - && val == leftChild.getVal()) { // left node is the leaf node - node.setVal(rightChild.getVal()); - node.setLeft(null); - node.setRight(null); - } else if (rightChild.getLeft() == null && rightChild.getRight() == null - && val == rightChild.getVal()) { // right node is the leaf node - node.setLeft(null); - node.setRight(null); - } else { - if (val <= node.getVal()) { - if (leftChild != null) { - node.setLeft(delete(leftChild, val)); - } - if (val == node.getVal()) { // duplicate node - node.setVal(getMostRight(leftChild).getVal()); // update the duplicate key - } - } else { - if (rightChild != null) { - node.setRight(delete(rightChild, val)); + if (leftChild.getLeft() == null && leftChild.getRight() == null + && val == leftChild.getVal()) { // left node is the leaf node + node.setVal(rightChild.getVal()); + node.setLeft(null); + node.setRight(null); + } else if (rightChild.getLeft() == null && rightChild.getRight() == null + && val == rightChild.getVal()) { // right node is the leaf node + node.setLeft(null); + node.setRight(null); + } else { + if (val <= node.getVal()) { + if (leftChild != null) { + node.setLeft(delete(leftChild, val)); + } + if (val == node.getVal()) { // duplicate node + node.setVal(getMostRight(leftChild).getVal()); // update the duplicate key + } + } else { + if (rightChild != null) { + node.setRight(delete(rightChild, val)); + } + } } - } + return rebalance(node); } - return rebalance(node); - } - /** - * Finds and returns the rightmost node in the Range Tree rooted at the given node. - * - * @param n The root node of a subtree to search in. - * @return The rightmost node in the subtree, or null if the input node is null. - */ - private static RangeTreeNode getMostRight(RangeTreeNode n) { - if (n.getRight() == null) { - return n; - } else { - return getMostRight(n.getRight()); + /** + * Finds and returns the rightmost node in the Range Tree rooted at the given node. + * + * @param n The root node of a subtree to search in. + * @return The rightmost node in the subtree, or null if the input node is null. + */ + private static RangeTreeNode getMostRight(RangeTreeNode n) { + if (n.getRight() == null) { + return n; + } else { + return getMostRight(n.getRight()); + } } - } - /** - * Performs a level order traversal of the Range Tree and prints the elements. - * This is not a necessary function for orthogonal range searching, but merely a utility function for debugging - * and visualisation purposes. - * - * @param root The root node of the Range Tree. - */ - public static void levelOrderTraversal(RangeTreeNode root) { - if (root == null) { - return; - } - Queue> queue = new LinkedList<>(); - queue.add(root); - while (!queue.isEmpty()) { - RangeTreeNode current = queue.poll(); - System.out.print(current.getVal() + " "); - if (current.getLeft() != null) { - queue.add(current.getLeft()); - } - if (current.getRight() != null) { - queue.add(current.getRight()); - } + /** + * Performs a level order traversal of the Range Tree and prints the elements. + * This is not a necessary function for orthogonal range searching, but merely a utility function for debugging + * and visualisation purposes. + * + * @param root The root node of the Range Tree. + */ + public static void levelOrderTraversal(RangeTreeNode root) { + if (root == null) { + return; + } + Queue> queue = new LinkedList<>(); + queue.add(root); + while (!queue.isEmpty()) { + RangeTreeNode current = queue.poll(); + System.out.print(current.getVal() + " "); + if (current.getLeft() != null) { + queue.add(current.getLeft()); + } + if (current.getRight() != null) { + queue.add(current.getRight()); + } + } } - } } diff --git a/src/main/java/algorithms/orthogonalRangeSearching/oneDim/README.md b/src/main/java/algorithms/orthogonalRangeSearching/oneDim/README.md index 5df29c01..eeb04ed0 100644 --- a/src/main/java/algorithms/orthogonalRangeSearching/oneDim/README.md +++ b/src/main/java/algorithms/orthogonalRangeSearching/oneDim/README.md @@ -4,9 +4,9 @@ specified 1D range (interval) in a collection of 1D data (e.g. Find me everyone between ages 22 and 27). Additionally, we also want to support efficient insertions of new data points into the maintained set. -One strategy is would be to sort all the data points in O(nlogn) time, then insertion would take O(n). We can binary -search the low and high of the specified range to return all data points within in O(logn) time. This would be a -reasonable approach if the no. of queries >> no. of insertions. +One strategy would be to sort all the data points in O(nlogn) time, then insertion would take O(n). We can binary +search the low and high of the specified range to return the start and end indices of all the data points within +in O(logn) time. This would be a reasonable approach if the no. of queries >> no. of insertions. In cases where the no. of insertions >> no. of queries, we might want to further optimise the time complexity of insertions to O(logn) using a 1D range tree. diff --git a/src/main/java/algorithms/orthogonalRangeSearching/twoDim/OrthogonalRangeSearching.java b/src/main/java/algorithms/orthogonalRangeSearching/twoDim/OrthogonalRangeSearching.java index c92e3e8c..a71ef5cf 100644 --- a/src/main/java/algorithms/orthogonalRangeSearching/twoDim/OrthogonalRangeSearching.java +++ b/src/main/java/algorithms/orthogonalRangeSearching/twoDim/OrthogonalRangeSearching.java @@ -1,11 +1,14 @@ package algorithms.orthogonalRangeSearching.twoDim; -import algorithms.orthogonalRangeSearching.RangeTreeNode; - import java.util.ArrayList; import java.util.Comparator; import java.util.List; +import algorithms.orthogonalRangeSearching.RangeTreeNode; + +/** + * This class performs 2 dimensional orthogonal range searching. + */ public class OrthogonalRangeSearching { /** @@ -80,8 +83,8 @@ private static RangeTreeNode buildYTreeHelper(List inputs, * Finds the X-split node in the X-tree based on the specified X-coordinate range. * * @param root The root node of the X-tree. - * @param xLow The lower bound of the X-coordinate range. - * @param xHigh The upper bound of the X-coordinate range. + * @param xLow The lower bound of the X-coordinate range. + * @param xHigh The upper bound of the X-coordinate range. * @return The X-split node or null if not found. */ public static RangeTreeNode findXSplit(RangeTreeNode root, int xLow, int xHigh) { @@ -102,63 +105,66 @@ public static RangeTreeNode findXSplit(RangeTreeNode root, } return v; } + /** * Performs a left traversal of the X-tree to find points within the specified range. * - * @param v The current node in the X-tree. - * @param xLow The lower bound of the X-coordinate range. - * @param xHigh The upper bound of the X-coordinate range. - * @param yLow The lower bound of the Y-coordinate range. - * @param yHigh The upper bound of the Y-coordinate range. + * @param v The current node in the X-tree. + * @param xLow The lower bound of the X-coordinate range. + * @param xHigh The upper bound of the X-coordinate range. + * @param yLow The lower bound of the Y-coordinate range. + * @param yHigh The upper bound of the Y-coordinate range. * @param result A list to store the results. */ - public static void XLeftTraversal(RangeTreeNode v, int xLow, int xHigh, int yLow, int yHigh, + public static void xLeftTraversal(RangeTreeNode v, int xLow, int xHigh, int yLow, int yHigh, ArrayList result) { if (v != null) { if (isLeaf(v) && v.getVal()[0] >= xLow && v.getVal()[0] <= xHigh) { //leaf - YSearch(v, yLow, yHigh, result); + ySearch(v, yLow, yHigh, result); } else { if (xLow <= v.getVal()[0]) { - XLeftTraversal(v.getLeft(), xLow, xHigh, yLow, yHigh, result); - YSearch(v.getRight(), yLow, yHigh, result); + xLeftTraversal(v.getLeft(), xLow, xHigh, yLow, yHigh, result); + ySearch(v.getRight(), yLow, yHigh, result); } else { - XLeftTraversal(v.getRight(), xLow, xHigh, yLow, yHigh, result); + xLeftTraversal(v.getRight(), xLow, xHigh, yLow, yHigh, result); } } } } + /** * Performs a right traversal of the X-tree to find points within the specified range. * - * @param v The current node in the X-tree. - * @param xLow The lower bound of the X-coordinate range. - * @param xHigh The upper bound of the X-coordinate range. - * @param yLow The lower bound of the Y-coordinate range. - * @param yHigh The upper bound of the Y-coordinate range. + * @param v The current node in the X-tree. + * @param xLow The lower bound of the X-coordinate range. + * @param xHigh The upper bound of the X-coordinate range. + * @param yLow The lower bound of the Y-coordinate range. + * @param yHigh The upper bound of the Y-coordinate range. * @param result A list to store the results. */ - public static void XRightTraversal(RangeTreeNode v, int xLow, int xHigh, int yLow, int yHigh, + public static void xRightTraversal(RangeTreeNode v, int xLow, int xHigh, int yLow, int yHigh, ArrayList result) { if (v != null) { if (isLeaf(v) && v.getVal()[0] >= xLow && v.getVal()[0] <= xHigh) { //leaf - YSearch(v, yLow, yHigh, result); + ySearch(v, yLow, yHigh, result); } else { if (xHigh >= v.getVal()[0]) { - YSearch(v.getLeft(), yLow, yHigh, result); - XRightTraversal(v.getRight(), xLow, xHigh, yLow, yHigh, result); + ySearch(v.getLeft(), yLow, yHigh, result); + xRightTraversal(v.getRight(), xLow, xHigh, yLow, yHigh, result); } else { - XRightTraversal(v.getLeft(), xLow, xHigh, yLow, yHigh, result); + xRightTraversal(v.getLeft(), xLow, xHigh, yLow, yHigh, result); } } } } + /** - * Finds the Y-split node in the X-tree based on the specified X-coordinate range. + * Finds the Y-split node in the Y-tree based on the specified Y-coordinate range. * - * @param root The root node of the X-tree. - * @param yLow The lower bound of the X-coordinate range. - * @param yHigh The upper bound of the X-coordinate range. - * @return The X-split node or null if not found. + * @param root The root node of the Y-tree. + * @param yLow The lower bound of the Y-coordinate range. + * @param yHigh The upper bound of the Y-coordinate range. + * @return The Y-split node or null if not found. */ public static RangeTreeNode findYSplit(RangeTreeNode root, int yLow, int yHigh) { RangeTreeNode v = root; @@ -210,16 +216,16 @@ public static void allLeafTraversal(RangeTreeNode v, List * @param low The lower bound of the Y-coordinate range. * @param result A list to store the results. */ - public static void YLeftTraversal(RangeTreeNode v, int low, List result) { + public static void yLeftTraversal(RangeTreeNode v, int low, List result) { if (v != null) { if (isLeaf(v)) { result.add(v.getVal()); } else { if (low <= v.getVal()[1]) { - YLeftTraversal(v.getLeft(), low, result); + yLeftTraversal(v.getLeft(), low, result); allLeafTraversal(v.getRight(), result); } else { // definitely a qualifying leaf has to exist - YLeftTraversal(v.getRight(), low, result); + yLeftTraversal(v.getRight(), low, result); } } } @@ -229,19 +235,19 @@ public static void YLeftTraversal(RangeTreeNode v, int low, List v, int high, List result) { + public static void yRightTraversal(RangeTreeNode v, int high, List result) { if (v != null) { if (isLeaf(v) && v.getVal()[1] <= high) { // leaf, need extra check result.add(v.getVal()); } else { if (high > v.getVal()[1]) { allLeafTraversal(v.getLeft(), result); - YRightTraversal(v.getRight(), high, result); + yRightTraversal(v.getRight(), high, result); } else { // a qualifying leaf might or might not exist, we are just exploring - YRightTraversal(v.getLeft(), high, result); + yRightTraversal(v.getLeft(), high, result); } } } @@ -255,7 +261,7 @@ public static void YRightTraversal(RangeTreeNode v, int high, List v, int yLow, int yHigh, ArrayList result) { + public static void ySearch(RangeTreeNode v, int yLow, int yHigh, ArrayList result) { if (v != null) { RangeTreeNode splitNodeY = findYSplit(v.getYTree(), yLow, yHigh); if (splitNodeY != null) { @@ -263,8 +269,8 @@ public static void YSearch(RangeTreeNode v, int yLow, int yHigh, Arra && splitNodeY.getVal()[1] >= yLow && splitNodeY.getVal()[1] <= yHigh) { // if split node is leaf result.add(splitNodeY.getVal()); } - YLeftTraversal(splitNodeY.getLeft(), yLow, result); - YRightTraversal(splitNodeY.getRight(), yHigh, result); + yLeftTraversal(splitNodeY.getLeft(), yLow, result); + yRightTraversal(splitNodeY.getRight(), yHigh, result); } } } @@ -272,11 +278,11 @@ public static void YSearch(RangeTreeNode v, int yLow, int yHigh, Arra /** * Searches for 2D points within the specified orthogonal range in the X-tree. * - * @param tree The root node of the X-tree. - * @param xLow The lower bound of the X-coordinate range. - * @param xHigh The upper bound of the X-coordinate range. - * @param yLow The lower bound of the Y-coordinate range. - * @param yHigh The upper bound of the Y-coordinate range. + * @param tree The root node of the X-tree. + * @param xLow The lower bound of the X-coordinate range. + * @param xHigh The upper bound of the X-coordinate range. + * @param yLow The lower bound of the Y-coordinate range. + * @param yHigh The upper bound of the Y-coordinate range. * @return A list of 2D points within the specified orthogonal range. */ public static List search(RangeTreeNode tree, int xLow, int xHigh, int yLow, int yHigh) { @@ -285,10 +291,10 @@ public static List search(RangeTreeNode tree, int xLow, in if (splitNodeX != null) { if (isLeaf(splitNodeX) && splitNodeX.getVal()[0] >= xLow && splitNodeX.getVal()[0] <= xHigh) { // if split node is leaf - YSearch(splitNodeX, yLow, yHigh, result); + ySearch(splitNodeX, yLow, yHigh, result); } - XLeftTraversal(splitNodeX.getLeft(), xLow, xHigh, yLow, yHigh, result); - XRightTraversal(splitNodeX.getRight(), xLow, xHigh, yLow, yHigh, result); + xLeftTraversal(splitNodeX.getLeft(), xLow, xHigh, yLow, yHigh, result); + xRightTraversal(splitNodeX.getRight(), xLow, xHigh, yLow, yHigh, result); } return result; } diff --git a/src/test/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearchingTest.java b/src/test/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearchingTest.java index 8ac057d3..4de82f5f 100644 --- a/src/test/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearchingTest.java +++ b/src/test/java/algorithms/orthogonalRangeSearching/oneDim/OrthogonalRangeSearchingTest.java @@ -1,66 +1,67 @@ package algorithms.orthogonalRangeSearching.oneDim; -import algorithms.orthogonalRangeSearching.RangeTreeNode; +import static org.junit.Assert.assertArrayEquals; + import org.junit.Test; -import static org.junit.Assert.assertArrayEquals; +import algorithms.orthogonalRangeSearching.RangeTreeNode; public class OrthogonalRangeSearchingTest { - @Test - public void test_OrthogonalRangeSearching() { + @Test + public void test_orthogonalRangeSearching() { - int[] firstInput = new int[] {7, 12, 25, 26, 40, 45}; - Object[] firstExpected = new Object[] {12, 25, 26, 40, 45}; - RangeTreeNode firstTree = OrthogonalRangeSearching.buildTree(firstInput, 0, firstInput.length - 1); - Object[] firstResult = OrthogonalRangeSearching.search(firstTree, 10, 50); - assertArrayEquals(firstExpected, firstResult); + int[] firstInput = new int[]{7, 12, 25, 26, 40, 45}; + Object[] firstExpected = new Object[]{12, 25, 26, 40, 45}; + RangeTreeNode firstTree = OrthogonalRangeSearching.buildTree(firstInput, 0, firstInput.length - 1); + Object[] firstResult = OrthogonalRangeSearching.search(firstTree, 10, 50); + assertArrayEquals(firstExpected, firstResult); - int[] secondInput = new int[] {-26, -7, -10, -40, -43}; - Object[] secondExpected = new Object[] {-26, -10, -7}; - RangeTreeNode secondTree = OrthogonalRangeSearching.buildTree(secondInput, 0, secondInput.length - 1); - Object[] secondResult = OrthogonalRangeSearching.search(secondTree, -30, -2); - assertArrayEquals(secondExpected, secondResult); + int[] secondInput = new int[]{-26, -7, -10, -40, -43}; + Object[] secondExpected = new Object[]{-26, -10, -7}; + RangeTreeNode secondTree = OrthogonalRangeSearching.buildTree(secondInput, 0, secondInput.length - 1); + Object[] secondResult = OrthogonalRangeSearching.search(secondTree, -30, -2); + assertArrayEquals(secondExpected, secondResult); - int[] thirdInput = new int[] {26, 7, 12, 40, 45}; - Object[] thirdExpected = new Object[] {12, 26}; - RangeTreeNode thirdTree = OrthogonalRangeSearching.buildTree(thirdInput, 0, thirdInput.length - 1); - Object[] thirdResult = OrthogonalRangeSearching.search(thirdTree, 10, 35); - assertArrayEquals(thirdExpected, thirdResult); + int[] thirdInput = new int[]{26, 7, 12, 40, 45}; + Object[] thirdExpected = new Object[]{12, 26}; + RangeTreeNode thirdTree = OrthogonalRangeSearching.buildTree(thirdInput, 0, thirdInput.length - 1); + Object[] thirdResult = OrthogonalRangeSearching.search(thirdTree, 10, 35); + assertArrayEquals(thirdExpected, thirdResult); - // for fourth input - // static queries - int[] fourthInput = new int[] {3, 19, 30, 49, 59, 70, 89, 100}; - Object[] fourthExpected = new Object[] {30, 49, 59, 70}; - RangeTreeNode fourthTree = OrthogonalRangeSearching.buildTree(fourthInput, 0, fourthInput.length - 1); - Object[] fourthResult = OrthogonalRangeSearching.search(fourthTree, 20, 71); - assertArrayEquals(fourthExpected, fourthResult); + // for fourth input + // static queries + int[] fourthInput = new int[]{3, 19, 30, 49, 59, 70, 89, 100}; + Object[] fourthExpected = new Object[]{30, 49, 59, 70}; + RangeTreeNode fourthTree = OrthogonalRangeSearching.buildTree(fourthInput, 0, fourthInput.length - 1); + Object[] fourthResult = OrthogonalRangeSearching.search(fourthTree, 20, 71); + assertArrayEquals(fourthExpected, fourthResult); - Object[] fifthExpected = new Object[] {49, 59, 70, 89, 100}; - Object[] fifthResult = OrthogonalRangeSearching.search(fourthTree, 31, 130); - assertArrayEquals(fifthExpected, fifthResult); + Object[] fifthExpected = new Object[]{49, 59, 70, 89, 100}; + Object[] fifthResult = OrthogonalRangeSearching.search(fourthTree, 31, 130); + assertArrayEquals(fifthExpected, fifthResult); - Object[] sixthExpected = new Object[] {59}; - Object[] sixthResult = OrthogonalRangeSearching.search(fourthTree, 59, 59); - assertArrayEquals(sixthExpected, sixthResult); + Object[] sixthExpected = new Object[]{59}; + Object[] sixthResult = OrthogonalRangeSearching.search(fourthTree, 59, 59); + assertArrayEquals(sixthExpected, sixthResult); - // dynamic updates then query + // dynamic updates then query - OrthogonalRangeSearching.configureTree(fourthTree); - fourthTree = OrthogonalRangeSearching.insert(fourthTree, 101); - Object[] seventhExpected = new Object[] {49, 59, 70, 89, 100, 101}; - Object[] seventhResult = OrthogonalRangeSearching.search(fourthTree, 31, 130); - assertArrayEquals(seventhExpected, seventhResult); + OrthogonalRangeSearching.configureTree(fourthTree); + fourthTree = OrthogonalRangeSearching.insert(fourthTree, 101); + Object[] seventhExpected = new Object[]{49, 59, 70, 89, 100, 101}; + Object[] seventhResult = OrthogonalRangeSearching.search(fourthTree, 31, 130); + assertArrayEquals(seventhExpected, seventhResult); - fourthTree = OrthogonalRangeSearching.insert(fourthTree, 46); - fourthTree = OrthogonalRangeSearching.insert(fourthTree, 32); - Object[] eighthExpected = new Object[] {30, 32, 46, 49, 59, 70}; - Object[] eighthResult = OrthogonalRangeSearching.search(fourthTree, 20, 71); - assertArrayEquals(eighthExpected, eighthResult); + fourthTree = OrthogonalRangeSearching.insert(fourthTree, 46); + fourthTree = OrthogonalRangeSearching.insert(fourthTree, 32); + Object[] eighthExpected = new Object[]{30, 32, 46, 49, 59, 70}; + Object[] eighthResult = OrthogonalRangeSearching.search(fourthTree, 20, 71); + assertArrayEquals(eighthExpected, eighthResult); - fourthTree = OrthogonalRangeSearching.delete(fourthTree, 32); - fourthTree = OrthogonalRangeSearching.delete(fourthTree, 59); - Object[] ninthExpected = new Object[] {30, 46, 49, 70}; - Object[] ninthResult = OrthogonalRangeSearching.search(fourthTree, 20, 72); - assertArrayEquals(ninthExpected, ninthResult); + fourthTree = OrthogonalRangeSearching.delete(fourthTree, 32); + fourthTree = OrthogonalRangeSearching.delete(fourthTree, 59); + Object[] ninthExpected = new Object[]{30, 46, 49, 70}; + Object[] ninthResult = OrthogonalRangeSearching.search(fourthTree, 20, 72); + assertArrayEquals(ninthExpected, ninthResult); } } diff --git a/src/test/java/algorithms/orthogonalRangeSearching/twoDim/OrthogonalRangeSearchingTest.java b/src/test/java/algorithms/orthogonalRangeSearching/twoDim/OrthogonalRangeSearchingTest.java index d0f52e95..27e6ac6f 100644 --- a/src/test/java/algorithms/orthogonalRangeSearching/twoDim/OrthogonalRangeSearchingTest.java +++ b/src/test/java/algorithms/orthogonalRangeSearching/twoDim/OrthogonalRangeSearchingTest.java @@ -1,47 +1,48 @@ package algorithms.orthogonalRangeSearching.twoDim; -import algorithms.orthogonalRangeSearching.RangeTreeNode; -import org.junit.Test; +import static org.junit.Assert.assertArrayEquals; import java.util.ArrayList; import java.util.List; -import static org.junit.Assert.assertArrayEquals; +import org.junit.Test; + +import algorithms.orthogonalRangeSearching.RangeTreeNode; public class OrthogonalRangeSearchingTest { @Test - public void test_OrthogonalRangeSearching() { + public void test_orthogonalRangeSearching() { ArrayList firstInput = new ArrayList<>(); - firstInput.add(new Integer[] {4, 5}); - firstInput.add(new Integer[] {3, 3}); - firstInput.add(new Integer[] {2, 4}); - firstInput.add(new Integer[] {1, 2}); - firstInput.add(new Integer[] {5, 2}); - firstInput.add(new Integer[] {6, 3}); - firstInput.add(new Integer[] {7, 1}); - firstInput.add(new Integer[] {8, 4}); + firstInput.add(new Integer[]{4, 5}); + firstInput.add(new Integer[]{3, 3}); + firstInput.add(new Integer[]{2, 4}); + firstInput.add(new Integer[]{1, 2}); + firstInput.add(new Integer[]{5, 2}); + firstInput.add(new Integer[]{6, 3}); + firstInput.add(new Integer[]{7, 1}); + firstInput.add(new Integer[]{8, 4}); ArrayList firstExpected = new ArrayList<>(); - firstExpected.add(new Integer[] {1, 2}); - firstExpected.add(new Integer[] {3, 3}); - firstExpected.add(new Integer[] {5, 2}); - firstExpected.add(new Integer[] {6, 3}); + firstExpected.add(new Integer[]{1, 2}); + firstExpected.add(new Integer[]{3, 3}); + firstExpected.add(new Integer[]{5, 2}); + firstExpected.add(new Integer[]{6, 3}); RangeTreeNode firstTree = OrthogonalRangeSearching.buildXTree(firstInput, 0, firstInput.size() - 1); - List firstResult = OrthogonalRangeSearching.search(firstTree, 1, 6,1, 3); + List firstResult = OrthogonalRangeSearching.search(firstTree, 1, 6, 1, 3); assertArrayEquals(firstExpected.toArray(), firstResult.toArray()); ArrayList secondExpected = new ArrayList<>(); - secondExpected.add(new Integer[] {6, 3}); - secondExpected.add(new Integer[] {7, 1}); - secondExpected.add(new Integer[] {8, 4}); - List secondResult = OrthogonalRangeSearching.search(firstTree, 6, 9,0, 4); + secondExpected.add(new Integer[]{6, 3}); + secondExpected.add(new Integer[]{7, 1}); + secondExpected.add(new Integer[]{8, 4}); + List secondResult = OrthogonalRangeSearching.search(firstTree, 6, 9, 0, 4); assertArrayEquals(secondExpected.toArray(), secondResult.toArray()); ArrayList thirdExpected = new ArrayList<>(); - List thirdResult = OrthogonalRangeSearching.search(firstTree, 6, 9,2, 2); + List thirdResult = OrthogonalRangeSearching.search(firstTree, 6, 9, 2, 2); assertArrayEquals(thirdExpected.toArray(), thirdResult.toArray()); } } From 05cacf238ec26c3dac0859125002f0801ff8a9e6 Mon Sep 17 00:00:00 2001 From: kaitinghh <114789615+kaitinghh@users.noreply.github.com> Date: Fri, 29 Mar 2024 12:25:12 +0800 Subject: [PATCH 30/51] docs: add link to main README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5fbf1829..109a1e50 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ Gradle is used for development. * [Trie](src/main/java/dataStructures/trie) * [B-Tree](src/main/java/dataStructures/bTree) * Red-Black Tree (Not covered in CS2040s but useful!) - * Orthogonal Range Searching (**WIP**) + * [Orthogonal Range Searching](src/main/java/algorithms/orthogonalRangeSearching) * Interval Trees (**WIP**) 5. [Binary Heap](src/main/java/dataStructures/heap) (Max heap) 6. [Disjoint Set / Union Find](src/main/java/dataStructures/disjointSet) From f30a77adaa9a2e7806f37c9ddd3e6f7a0b91501b Mon Sep 17 00:00:00 2001 From: 4ndrelim Date: Fri, 5 Apr 2024 23:00:07 +0800 Subject: [PATCH 31/51] refactor: DisjointSet --- docs/team/profiles.md | 2 +- .../disjointSet/quickFind/DisjointSet.java | 14 ++++++++++++++ .../disjointSet/weightedUnion/DisjointSet.java | 15 +++++++++++++++ .../disjointSet/quickFind/DisjointSetTest.java | 10 ++++++++++ .../weightedUnion/DisjointSetTest.java | 10 ++++++++++ 5 files changed, 50 insertions(+), 1 deletion(-) diff --git a/docs/team/profiles.md b/docs/team/profiles.md index c9040cf1..e33f656d 100644 --- a/docs/team/profiles.md +++ b/docs/team/profiles.md @@ -2,7 +2,7 @@ | Name | Description/About | Website (LinkedIn/GitHub/Personal) | Contributions | |-----------|-------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|-------------------------------------------------------------| -| Andre | Aspiring ML engineer. Developing this with wonderful ex-students. | You can find me [here](https://4ndrelim.github.io)! | Team lead | +| Andre | Aspiring ML engineer. Developing this with wonderful ex-students. | You can find me [here](https://4ndrelim.github.io) | Team lead | | Kai Ting | Likes algorithms and a committed TA! | [Linkedin](https://www.linkedin.com/in/kai-ting-ho-425181268/) | Cool sorting and obscure trees! B-Trees, ORS.. | | Changxian | DevOps is right up his alley! | ... | Hashing variants! BTS DevOps - configure Gradle & workflows | | Shu Heng | Interested in ML, aspiring researcher. | No website but here's my [Linkedin](https://www.linkedin.com/in/yeoshuheng), please give me a job :< | CS Fundamentals! Stacks and queues! RB-tree. | diff --git a/src/main/java/dataStructures/disjointSet/quickFind/DisjointSet.java b/src/main/java/dataStructures/disjointSet/quickFind/DisjointSet.java index f5a5dce8..d9ae7e64 100644 --- a/src/main/java/dataStructures/disjointSet/quickFind/DisjointSet.java +++ b/src/main/java/dataStructures/disjointSet/quickFind/DisjointSet.java @@ -7,6 +7,7 @@ /** * Implementation of quick-find structure; Turns a list of objects into a data structure that supports union operations + * Note DS structure is not suited with duplicate elements! * * @param generic type of object to be stored */ @@ -33,6 +34,19 @@ public DisjointSet(List objects) { } } + /** + * Constructor to initialize Disjoint Set with a known array of objects. + * @param objects + */ + public DisjointSet(T[] objects) { + identifier = new HashMap<>(); + int size = objects.length; + for (int i = 0; i < size; i++) { + // internally, component identity is tracked with integers + identifier.put(objects[i], identifier.size()); // each obj initialize with a unique identity using size; + } + } + public int size() { return identifier.size(); } diff --git a/src/main/java/dataStructures/disjointSet/weightedUnion/DisjointSet.java b/src/main/java/dataStructures/disjointSet/weightedUnion/DisjointSet.java index 6a2d47ed..9f1419f1 100644 --- a/src/main/java/dataStructures/disjointSet/weightedUnion/DisjointSet.java +++ b/src/main/java/dataStructures/disjointSet/weightedUnion/DisjointSet.java @@ -10,6 +10,7 @@ * Turns a list of objects into a data structure that supports union operations. *

* Note that implementation below includes path compression. Refer to README for more details + * Note DS structure is not suited with duplicate elements! * * @param generic type of object to be stored */ @@ -39,6 +40,20 @@ public DisjointSet(List objects) { } } + /** + * Constructor to initialize Disjoint Set structure with a known array of objects. + * @param objects + */ + public DisjointSet(T[] objects) { + parents = new HashMap<>(); + size = new HashMap<>(); + for (int i = 0; i < objects.length; i++) { + T obj = objects[i]; + parents.put(obj, obj); // initially, every object forms a tree, with itself as the root + size.put(obj, 1); // each tree has size 1 at the start + } + } + /** * Internal helper method to find the root (identifier) of an object. Note that path compression has been included. * A point of concern might be performing path compression would require updating the sizes tracked by each node diff --git a/src/test/java/dataStructures/disjointSet/quickFind/DisjointSetTest.java b/src/test/java/dataStructures/disjointSet/quickFind/DisjointSetTest.java index 7d0c1695..8338cecc 100644 --- a/src/test/java/dataStructures/disjointSet/quickFind/DisjointSetTest.java +++ b/src/test/java/dataStructures/disjointSet/quickFind/DisjointSetTest.java @@ -24,6 +24,16 @@ public void construct_shouldCorrectlyInitializeNonEmpty() { Assert.assertFalse(ds.find("andre", "kai ting")); } + @Test + public void construct_shouldCorrectlyInitializeNonEmptyArray() { + String[] lst = new String[] { "andre", "chang xian", "jun neng", "kai ting", "shu heng" }; + + DisjointSet ds = new DisjointSet<>(lst); + Assert.assertEquals(ds.size(), 5); + + Assert.assertFalse(ds.find("andre", "kai ting")); + } + @Test public void find_shouldCorrectlyFindItself() { List lst = Arrays.asList("andre", "chang xian", "jun neng"); diff --git a/src/test/java/dataStructures/disjointSet/weightedUnion/DisjointSetTest.java b/src/test/java/dataStructures/disjointSet/weightedUnion/DisjointSetTest.java index 4e923091..77fccebb 100644 --- a/src/test/java/dataStructures/disjointSet/weightedUnion/DisjointSetTest.java +++ b/src/test/java/dataStructures/disjointSet/weightedUnion/DisjointSetTest.java @@ -24,6 +24,16 @@ public void construct_shouldCorrectlyInitializeNonEmpty() { Assert.assertFalse(ds.find("andre", "kai ting")); } + @Test + public void construct_shouldCorrectlyInitializeNonEmptyArray() { + String[] lst = new String[] { "andre", "chang xian", "jun neng", "kai ting", "shu heng" }; + + DisjointSet ds = new DisjointSet<>(lst); + Assert.assertEquals(ds.size(), 5); + + Assert.assertFalse(ds.find("andre", "kai ting")); + } + @Test public void find_shouldCorrectlyFindItself() { List lst = Arrays.asList("andre", "chang xian", "jun neng"); From 250e9b2ceabcfcaf3ae089de8ff6def18e0957e3 Mon Sep 17 00:00:00 2001 From: junneng Date: Sun, 31 Dec 2023 21:31:19 +0800 Subject: [PATCH 32/51] Add Prim's algorithm --- .../minimumSpanningTree/prims/Edge.java | 24 +++ .../minimumSpanningTree/prims/Node.java | 64 +++++++ .../minimumSpanningTree/prims/Prim.java | 164 ++++++++++++++++++ 3 files changed, 252 insertions(+) create mode 100644 src/main/java/algorithms/minimumSpanningTree/prims/Edge.java create mode 100644 src/main/java/algorithms/minimumSpanningTree/prims/Node.java create mode 100644 src/main/java/algorithms/minimumSpanningTree/prims/Prim.java diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Edge.java b/src/main/java/algorithms/minimumSpanningTree/prims/Edge.java new file mode 100644 index 00000000..0ca05f86 --- /dev/null +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Edge.java @@ -0,0 +1,24 @@ +package algorithms.minimumSpanningTree.prims; + +/** + * Helper class to encapsulate information about an edge; + * specifically, tells us the weight of an edge and the node on the other end + * (assumes that the starting node of the edge is known) + */ +public class Edge { + private final int weight; + private final Node endNode; + + public Edge(int weight, Node endNode) { + this.weight = weight; + this.endNode = endNode; + } + + public Node getEndNode() { + return this.endNode; + } + + public int getWeight() { + return this.weight; + } +} \ No newline at end of file diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java new file mode 100644 index 00000000..8f0d33d6 --- /dev/null +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java @@ -0,0 +1,64 @@ +package algorithms.minimumSpanningTree.prims; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * Helper class to encapsulate information about a node; + * specifically, tells us the weight of an edge and the node on the other end + * (assumes that the starting node of the edge is known) + */ +public class Node { + private final List edges; + private boolean isVisited = false; + private int currMinDistance; + + public Node(List edges) { + this.edges = new ArrayList<>(edges); + } + public Node() { + this.edges = new ArrayList<>(); + } + + public List getEdges() { + return this.edges; + } + + public int getCurrMinDistance() { + return currMinDistance; + } + + public void setVisited(boolean isVisited) { + this.isVisited = isVisited; + } + + public boolean isVisited() { + return this.isVisited; + } + + public void setCurrMinDistance(int currMinDistance) { + this.currMinDistance = currMinDistance; + } + + public String toString() { + return this.edges.toString(); + } + + public void addEdge(Edge mstEdge) { + this.edges.add(mstEdge); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Node node = (Node) o; + return isVisited == node.isVisited && edges.equals(node.edges); + } + + @Override + public int hashCode() { + return Objects.hash(edges, isVisited); + } +} diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java new file mode 100644 index 00000000..b79182ed --- /dev/null +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java @@ -0,0 +1,164 @@ +package algorithms.minimumSpanningTree.prims; + +import java.util.*; + +/** + * Implementation of Prim's Algorithm to find MSTs + * Idea: + * Starting from any source (this will be the first node to be in the MST), + * pick the lightest outgoing edge, and include the node at the other end as part of a set of nodes S. + * Now repeatedly do the above by picking the lightest outgoing edge adjacent to any node in S. + * (ensuring the other end of the node is not already in the MST) + * Repeat until S contains all nodes in the graph. S is the MST. + * + * Motivating Example: Minimum Cost to Connect All Points + * + A -9- C -2- E + / / \ \ + 3 4 7 2 + / / \ / + F -1- B --5-- D +*/ + +/** + * Implementation 1: Using heap + * Time: O(V) + O(ElogV) (since heap could possibly hold E number of weights) + O(E-V) (nodes that have been 'seen' are still added to the heap, just not expanded) + O(V^2) + * Space: O(V) (hashmap to decide on MST) + O(E) (heap) = O(V+E) = O(E) + */ + +public class Prim { +// /** +// * points: Adjacency matrix that encapsulates the distance/weight between nodes +// * adjM[i][j] is the weight of the edge connecting points i and j; a value of 0 suggests there is no connection between i and j +// * @param adjM Adjacency matrix that encapsulates the distance/weight between nodes +// * @return minimum weight of the spanning tree +// */ +// public int minCostConnectPoints(int[][] adjM) { +// int v = adjM.length; +// int minCost = 0; +// Set mst = new HashSet<>(); +// mst.add(0); +// PriorityQueue pq = new PriorityQueue<>( +// (a, b) -> a.dist - b.dist +// ); +// for (int i = 0; i < v; i++) { +// if (!mst.contains(i)) { +// if (adjM[0][i] != 0) { // ensure valid edge +// pq.add(new Edge(adjM[0][i], i)); +// } +// } +// } +// while (mst.size() != v) { +// Edge popped = pq.poll(); +// if (mst.contains(popped.endNode)) { +// continue; +// } +// minCost += popped.dist; +// mst.add(popped.endNode); +// for (int i = 0; i < v; i++) { +// if (mst.contains(i)) { +// continue; +// } +// if (adjM[popped.endNode][i] != 0) { // ensure valid edge +// pq.add(new Edge(adjM[popped.endNode][i], i)); +// } +// } +// } +// return minCost; +// } +// +// /** +// * Alternative implementation that simply uses array to hold weights rather than heap. +// * Note: Starts from the node labelled 0 and repeatedly update +// * which stores the minimum weight from any node in the MST to other nodes. +// * Time: O(V) + O(V*2V) +// * Space: O(V) +// * @param adjM Adjacency matrix that encapsulates the distance/weight between nodes +// * @return minimum weight of the spanning tree +// */ +// public int minCostConnectPoints2(int[][] adjM) { +// int v = adjM.length; +// int[] weights = new int[v]; +// +// for (int i = 0; i < v; i++) { +// weights[i] = adjM[0][i]; +// } +// +// Set mst = new HashSet<>(); +// mst.add(0); // start from source 0 +// int ans = 0; +// while (mst.size() < v) { +// int next = v; +// for (int i = 0; i < v; i++) { +// if (!mst.contains(i)) { +// if (weights[i] != 0 && (next == v || weights[i] < weights[next])) { // first check for valid connection, then try to find min weight +// next = i; +// } +// } +// } +// mst.add(next); +// ans += weights[next]; +// +// for (int i = 0; i < v; i++) { +// if (!mst.contains(i)) { +// if (weights[i] == 0 || adjM[next][i] < weights[i]) { // update shortest dist to nodes that are not added to mst yet +// weights[i] = adjM[next][i]; +// } +// } +// } +// } +// return ans; +// } + + public static List getPrimsMST(List graph) { + PriorityQueue pq = new PriorityQueue<>( + (a, b) -> a.getCurrMinDistance() - b.getCurrMinDistance() + ); + + // Values in the map represent the corresponding node with only the edges in the MST + Map nodeToMSTNode = new HashMap<>(); + + // mstEdge map required to track the edges in the MST. The corresponding node is the start node of the edge. + Map mstEdge = new HashMap<>(); + + // Initialize each node's minDistance to infinity and add to the priority queue + for (Node node : graph) { + node.setCurrMinDistance(Integer.MAX_VALUE); + pq.add(node); + nodeToMSTNode.put(node, new Node()); // Create a corresponding MST node + } + + // Assuming graph is not empty and the start node is the first node + if (!graph.isEmpty()) { + graph.get(0).setCurrMinDistance(0); + } + + while (!pq.isEmpty()) { + Node current = pq.poll(); + current.setVisited(true); + + for (Edge edge : current.getEdges()) { + Node adjacent = edge.getEndNode(); + if (!adjacent.isVisited() && edge.getWeight() < adjacent.getCurrMinDistance()) { + pq.remove(adjacent); + adjacent.setCurrMinDistance(edge.getWeight()); + pq.add(adjacent); + mstEdge.put(edge, current); // Update the lightest valid outgoing edge + } + } + } + + // Populate the MST nodes with the edges to be included in the MST + for (Edge edge : mstEdge.keySet()) { + Node start = mstEdge.get(edge); + nodeToMSTNode.get(start).addEdge(edge); + } + + // Extract the nodes from the map to return them + return new ArrayList<>(nodeToMSTNode.values()); + } + +} + + + From 3e34e9f6b942efaeab0e79597323be7ac4c54b72 Mon Sep 17 00:00:00 2001 From: junneng Date: Sun, 31 Dec 2023 22:08:29 +0800 Subject: [PATCH 33/51] Update docs for Prim's algorithm --- .../java/algorithms/minimumSpanningTree/prims/Prim.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java index b79182ed..076f1c9f 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java @@ -7,10 +7,14 @@ * Idea: * Starting from any source (this will be the first node to be in the MST), * pick the lightest outgoing edge, and include the node at the other end as part of a set of nodes S. - * Now repeatedly do the above by picking the lightest outgoing edge adjacent to any node in S. + * + * Now repeatedly do the above by picking the lightest outgoing edge adjacent to any node in the MST. * (ensuring the other end of the node is not already in the MST) * Repeat until S contains all nodes in the graph. S is the MST. * + * Actual implementation: + * + * * Motivating Example: Minimum Cost to Connect All Points * A -9- C -2- E From 62529c504763a0d399889609faa6c42a206df2e5 Mon Sep 17 00:00:00 2001 From: junnengsoo Date: Wed, 31 Jan 2024 11:27:20 +0800 Subject: [PATCH 34/51] Remove Edge implementation, add adjacency list and identifiers --- .../minimumSpanningTree/prims/Edge.java | 24 --- .../minimumSpanningTree/prims/Node.java | 63 ++++---- .../minimumSpanningTree/prims/Prim.java | 145 ++++-------------- 3 files changed, 70 insertions(+), 162 deletions(-) delete mode 100644 src/main/java/algorithms/minimumSpanningTree/prims/Edge.java diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Edge.java b/src/main/java/algorithms/minimumSpanningTree/prims/Edge.java deleted file mode 100644 index 0ca05f86..00000000 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Edge.java +++ /dev/null @@ -1,24 +0,0 @@ -package algorithms.minimumSpanningTree.prims; - -/** - * Helper class to encapsulate information about an edge; - * specifically, tells us the weight of an edge and the node on the other end - * (assumes that the starting node of the edge is known) - */ -public class Edge { - private final int weight; - private final Node endNode; - - public Edge(int weight, Node endNode) { - this.weight = weight; - this.endNode = endNode; - } - - public Node getEndNode() { - return this.endNode; - } - - public int getWeight() { - return this.weight; - } -} \ No newline at end of file diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java index 8f0d33d6..649b0a83 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java @@ -1,52 +1,59 @@ package algorithms.minimumSpanningTree.prims; -import java.util.ArrayList; -import java.util.List; +import java.util.HashMap; +import java.util.Map; import java.util.Objects; -/** - * Helper class to encapsulate information about a node; - * specifically, tells us the weight of an edge and the node on the other end - * (assumes that the starting node of the edge is known) - */ public class Node { - private final List edges; private boolean isVisited = false; - private int currMinDistance; + private int currMinWeight; + private Map adjacentNodes; + private String identifier; // Unique identifier for the node - public Node(List edges) { - this.edges = new ArrayList<>(edges); + public Node(String identifier) { + this.adjacentNodes = new HashMap<>(); + this.identifier = identifier; } - public Node() { - this.edges = new ArrayList<>(); + + public Node(String identifier, Map adjacentNodes) { + this.identifier = identifier; + this.adjacentNodes = adjacentNodes; } - public List getEdges() { - return this.edges; + public Map getAdjacentNodes() { + return adjacentNodes; } - public int getCurrMinDistance() { - return currMinDistance; + public int getCurrMinWeight() { + return currMinWeight; } - public void setVisited(boolean isVisited) { - this.isVisited = isVisited; + public void setCurrMinWeight(int currMinWeight) { + this.currMinWeight = currMinWeight; } public boolean isVisited() { return this.isVisited; } - public void setCurrMinDistance(int currMinDistance) { - this.currMinDistance = currMinDistance; + public void setVisited(boolean isVisited) { + this.isVisited = isVisited; + } + + public String getIdentifier() { + return identifier; } - public String toString() { - return this.edges.toString(); + public void setIdentifier(String identifier) { + this.identifier = identifier; } - public void addEdge(Edge mstEdge) { - this.edges.add(mstEdge); + @Override + public String toString() { + return "Node{" + + "identifier='" + identifier + '\'' + + ", adjacentNodes=" + adjacentNodes + + '}'; } @Override @@ -54,11 +61,13 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Node node = (Node) o; - return isVisited == node.isVisited && edges.equals(node.edges); + return isVisited == node.isVisited && + Objects.equals(identifier, node.identifier) && + Objects.equals(adjacentNodes, node.adjacentNodes); } @Override public int hashCode() { - return Objects.hash(edges, isVisited); + return Objects.hash(identifier, adjacentNodes, isVisited); } } diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java index 076f1c9f..8c358883 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java @@ -1,6 +1,10 @@ package algorithms.minimumSpanningTree.prims; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.PriorityQueue; /** * Implementation of Prim's Algorithm to find MSTs @@ -23,145 +27,64 @@ / / \ / F -1- B --5-- D */ - -/** - * Implementation 1: Using heap - * Time: O(V) + O(ElogV) (since heap could possibly hold E number of weights) + O(E-V) (nodes that have been 'seen' are still added to the heap, just not expanded) + O(V^2) - * Space: O(V) (hashmap to decide on MST) + O(E) (heap) = O(V+E) = O(E) - */ - public class Prim { -// /** -// * points: Adjacency matrix that encapsulates the distance/weight between nodes -// * adjM[i][j] is the weight of the edge connecting points i and j; a value of 0 suggests there is no connection between i and j -// * @param adjM Adjacency matrix that encapsulates the distance/weight between nodes -// * @return minimum weight of the spanning tree -// */ -// public int minCostConnectPoints(int[][] adjM) { -// int v = adjM.length; -// int minCost = 0; -// Set mst = new HashSet<>(); -// mst.add(0); -// PriorityQueue pq = new PriorityQueue<>( -// (a, b) -> a.dist - b.dist -// ); -// for (int i = 0; i < v; i++) { -// if (!mst.contains(i)) { -// if (adjM[0][i] != 0) { // ensure valid edge -// pq.add(new Edge(adjM[0][i], i)); -// } -// } -// } -// while (mst.size() != v) { -// Edge popped = pq.poll(); -// if (mst.contains(popped.endNode)) { -// continue; -// } -// minCost += popped.dist; -// mst.add(popped.endNode); -// for (int i = 0; i < v; i++) { -// if (mst.contains(i)) { -// continue; -// } -// if (adjM[popped.endNode][i] != 0) { // ensure valid edge -// pq.add(new Edge(adjM[popped.endNode][i], i)); -// } -// } -// } -// return minCost; -// } -// -// /** -// * Alternative implementation that simply uses array to hold weights rather than heap. -// * Note: Starts from the node labelled 0 and repeatedly update -// * which stores the minimum weight from any node in the MST to other nodes. -// * Time: O(V) + O(V*2V) -// * Space: O(V) -// * @param adjM Adjacency matrix that encapsulates the distance/weight between nodes -// * @return minimum weight of the spanning tree -// */ -// public int minCostConnectPoints2(int[][] adjM) { -// int v = adjM.length; -// int[] weights = new int[v]; -// -// for (int i = 0; i < v; i++) { -// weights[i] = adjM[0][i]; -// } -// -// Set mst = new HashSet<>(); -// mst.add(0); // start from source 0 -// int ans = 0; -// while (mst.size() < v) { -// int next = v; -// for (int i = 0; i < v; i++) { -// if (!mst.contains(i)) { -// if (weights[i] != 0 && (next == v || weights[i] < weights[next])) { // first check for valid connection, then try to find min weight -// next = i; -// } -// } -// } -// mst.add(next); -// ans += weights[next]; -// -// for (int i = 0; i < v; i++) { -// if (!mst.contains(i)) { -// if (weights[i] == 0 || adjM[next][i] < weights[i]) { // update shortest dist to nodes that are not added to mst yet -// weights[i] = adjM[next][i]; -// } -// } -// } -// } -// return ans; -// } - public static List getPrimsMST(List graph) { PriorityQueue pq = new PriorityQueue<>( - (a, b) -> a.getCurrMinDistance() - b.getCurrMinDistance() + (a, b) -> a.getCurrMinWeight() - b.getCurrMinWeight() ); // Values in the map represent the corresponding node with only the edges in the MST Map nodeToMSTNode = new HashMap<>(); + Map parentInMST = new HashMap<>(); - // mstEdge map required to track the edges in the MST. The corresponding node is the start node of the edge. - Map mstEdge = new HashMap<>(); - - // Initialize each node's minDistance to infinity and add to the priority queue + // Initialize each node's minWeight to infinity and add to the priority queue for (Node node : graph) { - node.setCurrMinDistance(Integer.MAX_VALUE); + node.setCurrMinWeight(Integer.MAX_VALUE); pq.add(node); - nodeToMSTNode.put(node, new Node()); // Create a corresponding MST node + nodeToMSTNode.put(node, new Node(node.getIdentifier())); // Create a corresponding MST node + parentInMST.put(node, null); } // Assuming graph is not empty and the start node is the first node if (!graph.isEmpty()) { - graph.get(0).setCurrMinDistance(0); + graph.get(0).setCurrMinWeight(0); } while (!pq.isEmpty()) { Node current = pq.poll(); current.setVisited(true); - for (Edge edge : current.getEdges()) { - Node adjacent = edge.getEndNode(); - if (!adjacent.isVisited() && edge.getWeight() < adjacent.getCurrMinDistance()) { - pq.remove(adjacent); - adjacent.setCurrMinDistance(edge.getWeight()); - pq.add(adjacent); - mstEdge.put(edge, current); // Update the lightest valid outgoing edge + Map currentAdjacentNodes = current.getAdjacentNodes(); + + for (Map.Entry entry : currentAdjacentNodes.entrySet()) { + Node adjacent = entry.getKey(); + Integer weight = entry.getValue(); + + if (!adjacent.isVisited() && weight < adjacent.getCurrMinWeight()) { + adjacent.setCurrMinWeight(weight); + + // Update the parent in MST + parentInMST.put(adjacent, current); } } } - // Populate the MST nodes with the edges to be included in the MST - for (Edge edge : mstEdge.keySet()) { - Node start = mstEdge.get(edge); - nodeToMSTNode.get(start).addEdge(edge); + // Construct the MST using the parent-child relationships + for (Node originalNode : graph) { + Node mstNode = nodeToMSTNode.get(originalNode); + Node parent = parentInMST.get(originalNode); + + if (parent != null) { + Node mstParent = nodeToMSTNode.get(parent); + int weight = originalNode.getAdjacentNodes().get(parent); + mstParent.getAdjacentNodes().put(mstNode, weight); + mstNode.getAdjacentNodes().put(mstParent, weight); // For undirected graphs + } } // Extract the nodes from the map to return them return new ArrayList<>(nodeToMSTNode.values()); } - } From 8365586ca1f66925ed66b884eec08626bffaaacd Mon Sep 17 00:00:00 2001 From: junnengsoo Date: Wed, 31 Jan 2024 20:42:14 +0800 Subject: [PATCH 35/51] Add MST tests --- .../minimumSpanningTree/prims/Node.java | 7 +- .../minimumSpanningTree/prims/Prim.java | 4 +- .../minimumSpanningTree/prims/PrimsTest.java | 169 ++++++++++++++++++ 3 files changed, 173 insertions(+), 7 deletions(-) create mode 100644 src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java index 649b0a83..bb91e729 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java @@ -52,7 +52,6 @@ public void setIdentifier(String identifier) { public String toString() { return "Node{" + "identifier='" + identifier + '\'' + - ", adjacentNodes=" + adjacentNodes + '}'; } @@ -61,13 +60,11 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Node node = (Node) o; - return isVisited == node.isVisited && - Objects.equals(identifier, node.identifier) && - Objects.equals(adjacentNodes, node.adjacentNodes); + return Objects.equals(identifier, node.identifier); } @Override public int hashCode() { - return Objects.hash(identifier, adjacentNodes, isVisited); + return Objects.hash(identifier); } } diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java index 8c358883..da4cfff9 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java @@ -61,7 +61,9 @@ public static List getPrimsMST(List graph) { Integer weight = entry.getValue(); if (!adjacent.isVisited() && weight < adjacent.getCurrMinWeight()) { + pq.remove(adjacent); adjacent.setCurrMinWeight(weight); + pq.add(adjacent); // Update the parent in MST parentInMST.put(adjacent, current); @@ -87,5 +89,3 @@ public static List getPrimsMST(List graph) { } } - - diff --git a/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java b/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java new file mode 100644 index 00000000..96bc6784 --- /dev/null +++ b/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java @@ -0,0 +1,169 @@ +package algorithms.minimumSpanningTree.prims; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +public class PrimsTest { + @Test + public void testPrimsMST_SimpleGraph() { + // Graph setup + // A -1- B -1- C + Node nodeActualA = new Node("A"); + Node nodeActualB = new Node("B"); + Node nodeActualC = new Node("C"); + + nodeActualA.getAdjacentNodes().put(nodeActualB, 1); + nodeActualB.getAdjacentNodes().put(nodeActualA, 1); + nodeActualB.getAdjacentNodes().put(nodeActualC, 1); + nodeActualC.getAdjacentNodes().put(nodeActualB, 1); + + List graph = Arrays.asList(nodeActualA, nodeActualB, nodeActualC); + + // Run Prim's algorithm + List actualMST = Prim.getPrimsMST(graph); + + // Expected MST + // A -1- B -1- C + Node nodeExpectedA = new Node("A"); + Node nodeExpectedB = new Node("B"); + Node nodeExpectedC = new Node("C"); + + nodeExpectedA.getAdjacentNodes().put(nodeExpectedB, 1); + nodeExpectedB.getAdjacentNodes().put(nodeExpectedA, 1); + nodeExpectedB.getAdjacentNodes().put(nodeExpectedC, 1); + nodeExpectedC.getAdjacentNodes().put(nodeExpectedB, 1); + + // Expected MST (same as the original graph in this simple case) + List expectedMST = Arrays.asList(nodeExpectedA, nodeExpectedB, nodeExpectedC); + + expectedMST.sort(Comparator.comparing(Node::getIdentifier)); + actualMST.sort(Comparator.comparing(Node::getIdentifier)); + + // Assertion + assertGraphsEqual(expectedMST, actualMST); // Direct comparison of lists + } + + @Test + public void testPrimsMST_ComplexGraph() { + // Graph setup + // A + // / | \ + // 1 4 2 + // / | \ + // B --3-- D + // \ | / + // 2 3 3 + // \ | / + // C + Node nodeA = new Node("A"); + Node nodeB = new Node("B"); + Node nodeC = new Node("C"); + Node nodeD = new Node("D"); + + nodeA.getAdjacentNodes().put(nodeB, 1); + nodeA.getAdjacentNodes().put(nodeC, 4); + nodeA.getAdjacentNodes().put(nodeD, 2); + nodeB.getAdjacentNodes().put(nodeA, 1); + nodeB.getAdjacentNodes().put(nodeC, 3); + nodeB.getAdjacentNodes().put(nodeD, 2); + nodeC.getAdjacentNodes().put(nodeA, 4); + nodeC.getAdjacentNodes().put(nodeB, 3); + nodeC.getAdjacentNodes().put(nodeD, 3); + nodeD.getAdjacentNodes().put(nodeA, 2); + nodeD.getAdjacentNodes().put(nodeB, 2); + nodeD.getAdjacentNodes().put(nodeC, 3); + + List graph = Arrays.asList(nodeA, nodeB, nodeC, nodeD); + + // Run Prim's algorithm + List actualMST = Prim.getPrimsMST(graph); + + // Expected MST + // D -2- A -1- B -3- C + Node nodeExpectedA = new Node("A"); + Node nodeExpectedB = new Node("B"); + Node nodeExpectedC = new Node("C"); + Node nodeExpectedD = new Node("D"); + + nodeExpectedA.getAdjacentNodes().put(nodeExpectedB, 1); + nodeExpectedA.getAdjacentNodes().put(nodeExpectedD, 2); + nodeExpectedB.getAdjacentNodes().put(nodeExpectedA, 1); + nodeExpectedB.getAdjacentNodes().put(nodeExpectedC, 3); + nodeExpectedC.getAdjacentNodes().put(nodeExpectedB, 3); + nodeExpectedD.getAdjacentNodes().put(nodeExpectedA, 2); + + // Expected MST (based on the given graph) + List expectedMST = Arrays.asList(nodeExpectedA, nodeExpectedB, nodeExpectedC, nodeExpectedD); + + expectedMST.sort(Comparator.comparing(Node::getIdentifier)); + actualMST.sort(Comparator.comparing(Node::getIdentifier)); + + // Assertion + assertGraphsEqual(expectedMST, actualMST); // Direct comparison of lists + } + + private void assertGraphsEqual(List expected, List actual) { + if (expected.size() != actual.size()) { + fail("The MSTs do not have the same number of nodes. Expected size: " + + expected.size() + ", Actual size: " + actual.size()); + } + for (int i = 0; i < expected.size(); i++) { + Node expectedNode = expected.get(i); + Node actualNode = actual.get(i); + assertTrue("Nodes do not match at index " + i + ": Expected " + + expectedNode + ", Actual " + actualNode, + nodesAreEqual(expectedNode, actualNode)); + } + } + + private boolean nodesAreEqual(Node node1, Node node2) { + if (!node1.getIdentifier().equals(node2.getIdentifier())) { + fail("Node identifiers do not match: Expected " + + node1.getIdentifier() + ", Actual " + node2.getIdentifier()); + } + if (!nodesHaveSameEdges(node1, node2)) { + fail("Adjacent nodes do not match for Node " + node1.getIdentifier()); + } + return true; + } + + private boolean nodesHaveSameEdges(Node node1, Node node2) { + Map adj1 = node1.getAdjacentNodes(); + Map adj2 = node2.getAdjacentNodes(); + if (adj1.size() != adj2.size()) { + fail("Different number of adjacent nodes for Node " + node1.getIdentifier() + + ". Expected size: " + adj1.size() + ", Actual size: " + adj2.size()); + } + for (Map.Entry entry : adj1.entrySet()) { + Node key = findNodeById(adj2.keySet(), entry.getKey().getIdentifier()); + if (key == null) { + fail("Missing adjacent node '" + entry.getKey().getIdentifier() + + "' in Node " + node1.getIdentifier()); + } + if (!adj2.get(key).equals(entry.getValue())) { + fail("Edge weight does not match for edge " + node1.getIdentifier() + + "-" + key.getIdentifier() + ". Expected weight: " + + entry.getValue() + ", Actual weight: " + adj2.get(key)); + } + } + return true; + } + + + private Node findNodeById(Set nodes, String id) { + for (Node node : nodes) { + if (node.getIdentifier().equals(id)) { + return node; + } + } + return null; + } +} From f5ced439ea701713717b9dc3894459036ceeaeb6 Mon Sep 17 00:00:00 2001 From: junnengsoo Date: Wed, 31 Jan 2024 21:22:35 +0800 Subject: [PATCH 36/51] Resolve stylecheck --- .../minimumSpanningTree/prims/Node.java | 39 +++++++++++++++---- .../minimumSpanningTree/prims/Prim.java | 31 +++++---------- .../minimumSpanningTree/prims/PrimsTest.java | 10 ++--- 3 files changed, 46 insertions(+), 34 deletions(-) diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java index bb91e729..2219e5e3 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java @@ -4,17 +4,33 @@ import java.util.Map; import java.util.Objects; +/** + * Node class for Prim's algorithm. + * + * Each node has a unique identifier and contains a Map of adjacent nodes and their corresponding edge weights. + */ public class Node { private boolean isVisited = false; - private int currMinWeight; - private Map adjacentNodes; - private String identifier; // Unique identifier for the node + private int currMinWeight; // Current minimum weight to get to this node to calculate Prim's MST + private final Map adjacentNodes; + private String identifier; + /** + * Constructor for a node with no adjacent nodes. + * + * @param identifier Unique identifier for the node + */ public Node(String identifier) { this.adjacentNodes = new HashMap<>(); this.identifier = identifier; } + /** + * Constructor for a node with a list of adjacent nodes. + * + * @param identifier Unique identifier for the node + * @param adjacentNodes List of adjacent nodes + */ public Node(String identifier, Map adjacentNodes) { this.identifier = identifier; this.adjacentNodes = adjacentNodes; @@ -50,15 +66,22 @@ public void setIdentifier(String identifier) { @Override public String toString() { - return "Node{" + - "identifier='" + identifier + '\'' + - '}'; + return "Node{" + + "identifier='" + + identifier + '\'' + + '}'; } @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + + if (o == null || getClass() != o.getClass()) { + return false; + } + Node node = (Node) o; return Objects.equals(identifier, node.identifier); } diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java index da4cfff9..6a6cf7d5 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java @@ -6,32 +6,21 @@ import java.util.Map; import java.util.PriorityQueue; -/** +/** * Implementation of Prim's Algorithm to find MSTs - * Idea: - * Starting from any source (this will be the first node to be in the MST), - * pick the lightest outgoing edge, and include the node at the other end as part of a set of nodes S. - * - * Now repeatedly do the above by picking the lightest outgoing edge adjacent to any node in the MST. - * (ensuring the other end of the node is not already in the MST) + * Idea: + * Starting from any source (this will be the first node to be in the MST), pick the lightest outgoing edge, and + * include the node at the other end as part of a set of nodes S. Now repeatedly do the above by picking the lightest + * outgoing edge adjacent to any node in the MST (ensure the other end of the node is not already in the MST). * Repeat until S contains all nodes in the graph. S is the MST. - * * Actual implementation: - * - * - * Motivating Example: Minimum Cost to Connect All Points - * - A -9- C -2- E - / / \ \ - 3 4 7 2 - / / \ / - F -1- B --5-- D -*/ + * No Edge class was implemented. Instead, each node has a Map of adjacent nodes and their corresponding edge weights. + * To represent the MST, a new list of nodes is created with the same identifiers as the original graph, with each node + * containing only the edges in the MST. + */ public class Prim { public static List getPrimsMST(List graph) { - PriorityQueue pq = new PriorityQueue<>( - (a, b) -> a.getCurrMinWeight() - b.getCurrMinWeight() - ); + PriorityQueue pq = new PriorityQueue<>((a, b) -> a.getCurrMinWeight() - b.getCurrMinWeight()); // Values in the map represent the corresponding node with only the edges in the MST Map nodeToMSTNode = new HashMap<>(); diff --git a/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java b/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java index 96bc6784..31127790 100644 --- a/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java +++ b/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java @@ -1,6 +1,7 @@ package algorithms.minimumSpanningTree.prims; -import org.junit.Test; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.util.Arrays; import java.util.Comparator; @@ -8,12 +9,11 @@ import java.util.Map; import java.util.Set; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; +import org.junit.Test; public class PrimsTest { @Test - public void testPrimsMST_SimpleGraph() { + public void test_simpleGraph() { // Graph setup // A -1- B -1- C Node nodeActualA = new Node("A"); @@ -52,7 +52,7 @@ public void testPrimsMST_SimpleGraph() { } @Test - public void testPrimsMST_ComplexGraph() { + public void test_complexGraph() { // Graph setup // A // / | \ From 08c84a4368cd8469977ad7dd2f54012a861caf8e Mon Sep 17 00:00:00 2001 From: junnengsoo Date: Wed, 31 Jan 2024 22:39:30 +0800 Subject: [PATCH 37/51] Add MST README --- docs/assets/images/MST.jpg | Bin 0 -> 37478 bytes docs/assets/images/SPMST.jpg | Bin 0 -> 41740 bytes docs/assets/images/SPOriginal.jpg | Bin 0 -> 52627 bytes docs/assets/images/originalGraph.jpg | Bin 0 -> 44080 bytes .../algorithms/minimumSpanningTree/README.md | 33 ++++++++++++++++++ .../minimumSpanningTree/prims/README.md | 13 +++++++ 6 files changed, 46 insertions(+) create mode 100644 docs/assets/images/MST.jpg create mode 100644 docs/assets/images/SPMST.jpg create mode 100644 docs/assets/images/SPOriginal.jpg create mode 100644 docs/assets/images/originalGraph.jpg create mode 100644 src/main/java/algorithms/minimumSpanningTree/README.md create mode 100644 src/main/java/algorithms/minimumSpanningTree/prims/README.md diff --git a/docs/assets/images/MST.jpg b/docs/assets/images/MST.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1e28b3da91427e74e270b3df771f229a16dddf75 GIT binary patch literal 37478 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 Ptp*YJ6A*{-bLsy9PrM}D literal 0 HcmV?d00001 diff --git a/docs/assets/images/SPMST.jpg b/docs/assets/images/SPMST.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0e7342572a53cbb8d60636e1c27b4f8b1c951a90 GIT binary patch literal 41740 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 Do4U&{ literal 0 HcmV?d00001 diff --git a/docs/assets/images/SPOriginal.jpg b/docs/assets/images/SPOriginal.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0d96f87167f533409ddc86bb5beab326872ab24b GIT binary patch literal 52627 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 Zess2?bQOM`sef*d%1Jg5{{ZWQ|JhGh)o}m- literal 0 HcmV?d00001 diff --git a/src/main/java/algorithms/minimumSpanningTree/README.md b/src/main/java/algorithms/minimumSpanningTree/README.md new file mode 100644 index 00000000..e173d723 --- /dev/null +++ b/src/main/java/algorithms/minimumSpanningTree/README.md @@ -0,0 +1,33 @@ +# Minimum Spanning Tree Algorithms + +## Background + +Minimum Spanning Tree (MST) algorithms are used to find the minimum spanning tree of a weighted, connected graph. A +spanning tree of a graph is a connected, acyclic subgraph that includes all the vertices of the original graph. An MST +is a spanning tree with the minimum possible total edge weight. + +## Prim's Algorithm + +We will discuss more implementation-specific details and complexity analysis in the respective folders. In short, +1. [Prim's Algorithm](prims) is a greedy algorithm that finds the minimum spanning tree of a graph by starting from an +arbitrary node (vertex) and adding the edge with the minimum weight that connects the current tree to a new node, adding +the node to the current tree, until all nodes are included in the tree. + +## Notes + +### Difference between Minimum Spanning Tree and Shortest Path +It is important to note that a Minimum Spanning Tree of a graph does not represent the shortest path between all the +nodes. See below for an example: + +The below graph is a weighted, connected graph with 5 nodes and 6 edges: +![original graph img](../../../../../docs/assets/images/originalGraph.jpg) + +The following is the Minimum Spanning Tree of the above graph: +![MST img](../../../../../docs/assets/images/MST.jpg) + +Taking node A and D into consideration, the shortest path between them is A -> D, with a total weight of 4. +![SPOriginal img](../../../../../docs/assets/images/SPOriginal.jpg) + +However, the shortest path between A and D in the Minimum Spanning Tree is A -> C -> D, with a total weight of 5, which +is not the shortest path in the original graph. +![SPMST img](../../../../../docs/assets/images/SPMST.jpg) diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/README.md b/src/main/java/algorithms/minimumSpanningTree/prims/README.md new file mode 100644 index 00000000..f99d3025 --- /dev/null +++ b/src/main/java/algorithms/minimumSpanningTree/prims/README.md @@ -0,0 +1,13 @@ +# Prim's Algorithm + +## Background + +Prim's Algorithm is a greedy algorithm that finds the minimum spanning tree of a graph by starting from an +arbitrary node (vertex) and adding the edge with the minimum weight that connects the current tree to a new node, adding +the node to the current tree, until all nodes are included in the tree. + +## Complexity Analysis + +## Notes + +### Difference between Prim's Algorithm and Dijkstra's Algorithm \ No newline at end of file From 4852a7e34bfcc3c1830ed9f8ee754659a8936dfe Mon Sep 17 00:00:00 2001 From: junnengsoo Date: Tue, 26 Mar 2024 20:22:34 +0800 Subject: [PATCH 38/51] Use adjacency matrix instead of hash map for tracking of nodes --- .../minimumSpanningTree/prims/Node.java | 70 ++++++------------- .../minimumSpanningTree/prims/Prim.java | 63 ++++++----------- 2 files changed, 45 insertions(+), 88 deletions(-) diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java index 2219e5e3..c149e68e 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java @@ -1,45 +1,19 @@ package algorithms.minimumSpanningTree.prims; -import java.util.HashMap; -import java.util.Map; import java.util.Objects; -/** - * Node class for Prim's algorithm. - * - * Each node has a unique identifier and contains a Map of adjacent nodes and their corresponding edge weights. - */ public class Node { private boolean isVisited = false; - private int currMinWeight; // Current minimum weight to get to this node to calculate Prim's MST - private final Map adjacentNodes; + private int currMinWeight = Integer.MAX_VALUE; // Current minimum weight to get to this node + private int index; // Index of this node in the adjacency matrix private String identifier; - /** - * Constructor for a node with no adjacent nodes. - * - * @param identifier Unique identifier for the node - */ - public Node(String identifier) { - this.adjacentNodes = new HashMap<>(); + public Node(String identifier, int index) { this.identifier = identifier; + this.index = index; } - /** - * Constructor for a node with a list of adjacent nodes. - * - * @param identifier Unique identifier for the node - * @param adjacentNodes List of adjacent nodes - */ - public Node(String identifier, Map adjacentNodes) { - this.identifier = identifier; - this.adjacentNodes = adjacentNodes; - } - - public Map getAdjacentNodes() { - return adjacentNodes; - } - + // Getter and setter for currMinWeight public int getCurrMinWeight() { return currMinWeight; } @@ -48,46 +22,46 @@ public void setCurrMinWeight(int currMinWeight) { this.currMinWeight = currMinWeight; } + // Getter and setter for isVisited public boolean isVisited() { - return this.isVisited; + return isVisited; } public void setVisited(boolean isVisited) { this.isVisited = isVisited; } + // Getter for identifier public String getIdentifier() { return identifier; } - public void setIdentifier(String identifier) { - this.identifier = identifier; + // Getter and setter for index + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; } + // toString method @Override public String toString() { - return "Node{" - + "identifier='" - + identifier + '\'' - + '}'; + return "Node{" + "identifier='" + identifier + '\'' + ", index=" + index + '}'; } + // equals and hashCode based on identifier and index @Override public boolean equals(Object o) { - if (this == o) { - return true; - } - - if (o == null || getClass() != o.getClass()) { - return false; - } - + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; Node node = (Node) o; - return Objects.equals(identifier, node.identifier); + return index == node.index && Objects.equals(identifier, node.identifier); } @Override public int hashCode() { - return Objects.hash(identifier); + return Objects.hash(identifier, index); } } diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java index 6a6cf7d5..f5ec6752 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java @@ -19,62 +19,45 @@ * containing only the edges in the MST. */ public class Prim { - public static List getPrimsMST(List graph) { + public static int[][] getPrimsMST(Node[] nodes, int[][] adjacencyMatrix) { PriorityQueue pq = new PriorityQueue<>((a, b) -> a.getCurrMinWeight() - b.getCurrMinWeight()); + int[][] mstMatrix = new int[nodes.length][nodes.length]; // MST adjacency matrix - // Values in the map represent the corresponding node with only the edges in the MST - Map nodeToMSTNode = new HashMap<>(); - Map parentInMST = new HashMap<>(); + // Initialize the MST matrix to represent no edges with Integer.MAX_VALUE + for (int i = 0; i < nodes.length; i++) { + for (int j = 0; j < nodes.length; j++) { + mstMatrix[i][j] = Integer.MAX_VALUE; + } + } - // Initialize each node's minWeight to infinity and add to the priority queue - for (Node node : graph) { + // Initialize all nodes' currMinWeight to infinity, except the first node + for (Node node : nodes) { node.setCurrMinWeight(Integer.MAX_VALUE); pq.add(node); - nodeToMSTNode.put(node, new Node(node.getIdentifier())); // Create a corresponding MST node - parentInMST.put(node, null); - } - - // Assuming graph is not empty and the start node is the first node - if (!graph.isEmpty()) { - graph.get(0).setCurrMinWeight(0); } while (!pq.isEmpty()) { Node current = pq.poll(); current.setVisited(true); - Map currentAdjacentNodes = current.getAdjacentNodes(); - - for (Map.Entry entry : currentAdjacentNodes.entrySet()) { - Node adjacent = entry.getKey(); - Integer weight = entry.getValue(); + int currentIndex = current.getIndex(); - if (!adjacent.isVisited() && weight < adjacent.getCurrMinWeight()) { - pq.remove(adjacent); - adjacent.setCurrMinWeight(weight); - pq.add(adjacent); + for (int i = 0; i < nodes.length; i++) { + if (adjacencyMatrix[currentIndex][i] != Integer.MAX_VALUE && !nodes[i].isVisited()) { + int weight = adjacencyMatrix[currentIndex][i]; - // Update the parent in MST - parentInMST.put(adjacent, current); + if (weight < nodes[i].getCurrMinWeight()) { + pq.remove(nodes[i]); + nodes[i].setCurrMinWeight(weight); + pq.add(nodes[i]); + // Update the MST matrix + mstMatrix[currentIndex][i] = weight; + mstMatrix[i][currentIndex] = weight; // For undirected graphs + } } } } - - // Construct the MST using the parent-child relationships - for (Node originalNode : graph) { - Node mstNode = nodeToMSTNode.get(originalNode); - Node parent = parentInMST.get(originalNode); - - if (parent != null) { - Node mstParent = nodeToMSTNode.get(parent); - int weight = originalNode.getAdjacentNodes().get(parent); - mstParent.getAdjacentNodes().put(mstNode, weight); - mstNode.getAdjacentNodes().put(mstParent, weight); // For undirected graphs - } - } - - // Extract the nodes from the map to return them - return new ArrayList<>(nodeToMSTNode.values()); + return mstMatrix; } } From 84d35f796bd7122b5b370f70a72d6dde9d8da669 Mon Sep 17 00:00:00 2001 From: junnengsoo Date: Tue, 26 Mar 2024 22:42:32 +0800 Subject: [PATCH 39/51] Add adjacency matrix and new test cases --- .../minimumSpanningTree/prims/Node.java | 48 ++--- .../minimumSpanningTree/prims/Prim.java | 37 ++-- .../minimumSpanningTree/prims/PrimsTest.java | 192 +++++------------- 3 files changed, 101 insertions(+), 176 deletions(-) diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java index c149e68e..de39584d 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java @@ -2,18 +2,28 @@ import java.util.Objects; +/** + * Node class to represent a node in the graph + */ public class Node { private boolean isVisited = false; private int currMinWeight = Integer.MAX_VALUE; // Current minimum weight to get to this node private int index; // Index of this node in the adjacency matrix - private String identifier; + private final String identifier; + /** + * Constructor + * @param identifier + * @param index + */ public Node(String identifier, int index) { this.identifier = identifier; this.index = index; } - // Getter and setter for currMinWeight + /** + * Getter and setter for currMinWeight + */ public int getCurrMinWeight() { return currMinWeight; } @@ -22,21 +32,26 @@ public void setCurrMinWeight(int currMinWeight) { this.currMinWeight = currMinWeight; } - // Getter and setter for isVisited + /** + * Getter for identifier + * @return identifier + */ public boolean isVisited() { return isVisited; } + /** + * Setter for isVisited + * @param isVisited + */ public void setVisited(boolean isVisited) { this.isVisited = isVisited; } - // Getter for identifier - public String getIdentifier() { - return identifier; - } - - // Getter and setter for index + /** + * Getter for identifier + * @return identifier + */ public int getIndex() { return index; } @@ -45,23 +60,8 @@ public void setIndex(int index) { this.index = index; } - // toString method @Override public String toString() { return "Node{" + "identifier='" + identifier + '\'' + ", index=" + index + '}'; } - - // equals and hashCode based on identifier and index - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Node node = (Node) o; - return index == node.index && Objects.equals(identifier, node.identifier); - } - - @Override - public int hashCode() { - return Objects.hash(identifier, index); - } } diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java index f5ec6752..6466b402 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java @@ -1,9 +1,6 @@ package algorithms.minimumSpanningTree.prims; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.Arrays; import java.util.PriorityQueue; /** @@ -14,19 +11,26 @@ * outgoing edge adjacent to any node in the MST (ensure the other end of the node is not already in the MST). * Repeat until S contains all nodes in the graph. S is the MST. * Actual implementation: - * No Edge class was implemented. Instead, each node has a Map of adjacent nodes and their corresponding edge weights. - * To represent the MST, a new list of nodes is created with the same identifiers as the original graph, with each node - * containing only the edges in the MST. + * No Edge class was implemented. Instead, the weights of the edges are stored in a 2D array adjacency matrix. + * A Node class is implemented to encapsulate a isVisited flag and the current minimum weight to reach the node. */ public class Prim { public static int[][] getPrimsMST(Node[] nodes, int[][] adjacencyMatrix) { PriorityQueue pq = new PriorityQueue<>((a, b) -> a.getCurrMinWeight() - b.getCurrMinWeight()); int[][] mstMatrix = new int[nodes.length][nodes.length]; // MST adjacency matrix - // Initialize the MST matrix to represent no edges with Integer.MAX_VALUE + // Initialize mstMatrix with all edges set to Integer.MAX_VALUE + for (int[] row : mstMatrix) { + Arrays.fill(row, Integer.MAX_VALUE); + } + + int[] parent = new int[nodes.length]; // To track the parent node of each node in the MST + Arrays.fill(parent, -1); // Initialize parent array with -1, indicating no parent + + // Initialize the MST matrix to represent no edges with Integer.MAX_VALUE and 0 for self loops for (int i = 0; i < nodes.length; i++) { for (int j = 0; j < nodes.length; j++) { - mstMatrix[i][j] = Integer.MAX_VALUE; + mstMatrix[i][j] = (i == j) ? 0 : Integer.MAX_VALUE; } } @@ -50,13 +54,22 @@ public static int[][] getPrimsMST(Node[] nodes, int[][] adjacencyMatrix) { pq.remove(nodes[i]); nodes[i].setCurrMinWeight(weight); pq.add(nodes[i]); - // Update the MST matrix - mstMatrix[currentIndex][i] = weight; - mstMatrix[i][currentIndex] = weight; // For undirected graphs + parent[i] = currentIndex; // Set current node as parent of adjacent node } } } } + + // Build MST matrix based on parent array + for (int i = 1; i < nodes.length; i++) { + int p = parent[i]; + if (p != -1) { + int weight = adjacencyMatrix[p][i]; + mstMatrix[p][i] = weight; + mstMatrix[i][p] = weight; // For undirected graphs + } + } + return mstMatrix; } } diff --git a/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java b/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java index 31127790..36830e82 100644 --- a/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java +++ b/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java @@ -1,169 +1,81 @@ package algorithms.minimumSpanningTree.prims; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.Arrays; -import java.util.Comparator; -import java.util.List; -import java.util.Map; -import java.util.Set; +import static org.junit.Assert.assertArrayEquals; import org.junit.Test; public class PrimsTest { + @Test public void test_simpleGraph() { - // Graph setup + // Graph setup (Adjacency Matrix) // A -1- B -1- C - Node nodeActualA = new Node("A"); - Node nodeActualB = new Node("B"); - Node nodeActualC = new Node("C"); - - nodeActualA.getAdjacentNodes().put(nodeActualB, 1); - nodeActualB.getAdjacentNodes().put(nodeActualA, 1); - nodeActualB.getAdjacentNodes().put(nodeActualC, 1); - nodeActualC.getAdjacentNodes().put(nodeActualB, 1); - - List graph = Arrays.asList(nodeActualA, nodeActualB, nodeActualC); + int[][] adjacencyMatrix = { + {0, 1, 1}, // A: A-B, A-C + {1, 0, 1}, // B: B-A, B-C + {1, 1, 0} // C: C-A, C-B + }; + + Node[] nodes = { + new Node("A", 0), + new Node("B", 1), + new Node("C", 2) + }; // Run Prim's algorithm - List actualMST = Prim.getPrimsMST(graph); + int[][] actualMST = Prim.getPrimsMST(nodes, adjacencyMatrix); // Expected MST // A -1- B -1- C - Node nodeExpectedA = new Node("A"); - Node nodeExpectedB = new Node("B"); - Node nodeExpectedC = new Node("C"); - - nodeExpectedA.getAdjacentNodes().put(nodeExpectedB, 1); - nodeExpectedB.getAdjacentNodes().put(nodeExpectedA, 1); - nodeExpectedB.getAdjacentNodes().put(nodeExpectedC, 1); - nodeExpectedC.getAdjacentNodes().put(nodeExpectedB, 1); - - // Expected MST (same as the original graph in this simple case) - List expectedMST = Arrays.asList(nodeExpectedA, nodeExpectedB, nodeExpectedC); - - expectedMST.sort(Comparator.comparing(Node::getIdentifier)); - actualMST.sort(Comparator.comparing(Node::getIdentifier)); + int[][] expectedMST = { + {0, 1, 1}, // A: A-B, A-C + {1, 0, Integer.MAX_VALUE}, // B: B-A + {1, Integer.MAX_VALUE, 0} // C: C-A + }; // Assertion - assertGraphsEqual(expectedMST, actualMST); // Direct comparison of lists + assertArrayEquals(expectedMST, actualMST); } @Test public void test_complexGraph() { // Graph setup - // A - // / | \ - // 1 4 2 - // / | \ - // B --3-- D - // \ | / - // 2 3 3 - // \ | / - // C - Node nodeA = new Node("A"); - Node nodeB = new Node("B"); - Node nodeC = new Node("C"); - Node nodeD = new Node("D"); - - nodeA.getAdjacentNodes().put(nodeB, 1); - nodeA.getAdjacentNodes().put(nodeC, 4); - nodeA.getAdjacentNodes().put(nodeD, 2); - nodeB.getAdjacentNodes().put(nodeA, 1); - nodeB.getAdjacentNodes().put(nodeC, 3); - nodeB.getAdjacentNodes().put(nodeD, 2); - nodeC.getAdjacentNodes().put(nodeA, 4); - nodeC.getAdjacentNodes().put(nodeB, 3); - nodeC.getAdjacentNodes().put(nodeD, 3); - nodeD.getAdjacentNodes().put(nodeA, 2); - nodeD.getAdjacentNodes().put(nodeB, 2); - nodeD.getAdjacentNodes().put(nodeC, 3); - - List graph = Arrays.asList(nodeA, nodeB, nodeC, nodeD); + // A + // / | \ + // 1 4 2 + /// | \ + //B --3-- D + // \ | / + // 2 4 3 + // \|/ + // C + int[][] adjacencyMatrix = { + {0, 1, 4, 2}, // A: A-B, A-C, A-D + {1, 0, 2, 3}, // B: B-A, B-C, B-D + {4, 2, 0, 3}, // C: C-A, C-B, C-D + {2, 3, 3, 0} // D: D-A, D-B, D-C + }; + + Node[] nodes = { + new Node("A", 0), + new Node("B", 1), + new Node("C", 2), + new Node("D", 3) + }; // Run Prim's algorithm - List actualMST = Prim.getPrimsMST(graph); + int[][] actualMST = Prim.getPrimsMST(nodes, adjacencyMatrix); // Expected MST - // D -2- A -1- B -3- C - Node nodeExpectedA = new Node("A"); - Node nodeExpectedB = new Node("B"); - Node nodeExpectedC = new Node("C"); - Node nodeExpectedD = new Node("D"); - - nodeExpectedA.getAdjacentNodes().put(nodeExpectedB, 1); - nodeExpectedA.getAdjacentNodes().put(nodeExpectedD, 2); - nodeExpectedB.getAdjacentNodes().put(nodeExpectedA, 1); - nodeExpectedB.getAdjacentNodes().put(nodeExpectedC, 3); - nodeExpectedC.getAdjacentNodes().put(nodeExpectedB, 3); - nodeExpectedD.getAdjacentNodes().put(nodeExpectedA, 2); - - // Expected MST (based on the given graph) - List expectedMST = Arrays.asList(nodeExpectedA, nodeExpectedB, nodeExpectedC, nodeExpectedD); - - expectedMST.sort(Comparator.comparing(Node::getIdentifier)); - actualMST.sort(Comparator.comparing(Node::getIdentifier)); + // Based on the graph, assuming the MST is correctly computed + int[][] expectedMST = { + {0, 1, Integer.MAX_VALUE, 2}, // A: A-B, A-D + {1, 0, 2, Integer.MAX_VALUE}, // B: B-A, B-C + {Integer.MAX_VALUE, 2, 0, Integer.MAX_VALUE}, // C: C-B + {2, Integer.MAX_VALUE, Integer.MAX_VALUE, 0} // D: D-A + }; // Assertion - assertGraphsEqual(expectedMST, actualMST); // Direct comparison of lists - } - - private void assertGraphsEqual(List expected, List actual) { - if (expected.size() != actual.size()) { - fail("The MSTs do not have the same number of nodes. Expected size: " - + expected.size() + ", Actual size: " + actual.size()); - } - for (int i = 0; i < expected.size(); i++) { - Node expectedNode = expected.get(i); - Node actualNode = actual.get(i); - assertTrue("Nodes do not match at index " + i + ": Expected " - + expectedNode + ", Actual " + actualNode, - nodesAreEqual(expectedNode, actualNode)); - } - } - - private boolean nodesAreEqual(Node node1, Node node2) { - if (!node1.getIdentifier().equals(node2.getIdentifier())) { - fail("Node identifiers do not match: Expected " - + node1.getIdentifier() + ", Actual " + node2.getIdentifier()); - } - if (!nodesHaveSameEdges(node1, node2)) { - fail("Adjacent nodes do not match for Node " + node1.getIdentifier()); - } - return true; - } - - private boolean nodesHaveSameEdges(Node node1, Node node2) { - Map adj1 = node1.getAdjacentNodes(); - Map adj2 = node2.getAdjacentNodes(); - if (adj1.size() != adj2.size()) { - fail("Different number of adjacent nodes for Node " + node1.getIdentifier() - + ". Expected size: " + adj1.size() + ", Actual size: " + adj2.size()); - } - for (Map.Entry entry : adj1.entrySet()) { - Node key = findNodeById(adj2.keySet(), entry.getKey().getIdentifier()); - if (key == null) { - fail("Missing adjacent node '" + entry.getKey().getIdentifier() - + "' in Node " + node1.getIdentifier()); - } - if (!adj2.get(key).equals(entry.getValue())) { - fail("Edge weight does not match for edge " + node1.getIdentifier() - + "-" + key.getIdentifier() + ". Expected weight: " - + entry.getValue() + ", Actual weight: " + adj2.get(key)); - } - } - return true; - } - - - private Node findNodeById(Set nodes, String id) { - for (Node node : nodes) { - if (node.getIdentifier().equals(id)) { - return node; - } - } - return null; + assertArrayEquals(expectedMST, actualMST); } } From 79e65ed269242f3ede07aad174a438842dd1ca8a Mon Sep 17 00:00:00 2001 From: junneng Date: Sun, 31 Dec 2023 21:31:19 +0800 Subject: [PATCH 40/51] Add Prim's algorithm --- .../minimumSpanningTree/prims/Edge.java | 24 +++ .../minimumSpanningTree/prims/Node.java | 77 ++++---- .../minimumSpanningTree/prims/Prim.java | 182 +++++++++++++----- 3 files changed, 196 insertions(+), 87 deletions(-) create mode 100644 src/main/java/algorithms/minimumSpanningTree/prims/Edge.java diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Edge.java b/src/main/java/algorithms/minimumSpanningTree/prims/Edge.java new file mode 100644 index 00000000..0ca05f86 --- /dev/null +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Edge.java @@ -0,0 +1,24 @@ +package algorithms.minimumSpanningTree.prims; + +/** + * Helper class to encapsulate information about an edge; + * specifically, tells us the weight of an edge and the node on the other end + * (assumes that the starting node of the edge is known) + */ +public class Edge { + private final int weight; + private final Node endNode; + + public Edge(int weight, Node endNode) { + this.weight = weight; + this.endNode = endNode; + } + + public Node getEndNode() { + return this.endNode; + } + + public int getWeight() { + return this.weight; + } +} \ No newline at end of file diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java index de39584d..8f0d33d6 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java @@ -1,67 +1,64 @@ package algorithms.minimumSpanningTree.prims; +import java.util.ArrayList; +import java.util.List; import java.util.Objects; /** - * Node class to represent a node in the graph + * Helper class to encapsulate information about a node; + * specifically, tells us the weight of an edge and the node on the other end + * (assumes that the starting node of the edge is known) */ public class Node { + private final List edges; private boolean isVisited = false; - private int currMinWeight = Integer.MAX_VALUE; // Current minimum weight to get to this node - private int index; // Index of this node in the adjacency matrix - private final String identifier; + private int currMinDistance; - /** - * Constructor - * @param identifier - * @param index - */ - public Node(String identifier, int index) { - this.identifier = identifier; - this.index = index; + public Node(List edges) { + this.edges = new ArrayList<>(edges); } - - /** - * Getter and setter for currMinWeight - */ - public int getCurrMinWeight() { - return currMinWeight; + public Node() { + this.edges = new ArrayList<>(); } - public void setCurrMinWeight(int currMinWeight) { - this.currMinWeight = currMinWeight; + public List getEdges() { + return this.edges; } - /** - * Getter for identifier - * @return identifier - */ - public boolean isVisited() { - return isVisited; + public int getCurrMinDistance() { + return currMinDistance; } - /** - * Setter for isVisited - * @param isVisited - */ public void setVisited(boolean isVisited) { this.isVisited = isVisited; } - /** - * Getter for identifier - * @return identifier - */ - public int getIndex() { - return index; + public boolean isVisited() { + return this.isVisited; } - public void setIndex(int index) { - this.index = index; + public void setCurrMinDistance(int currMinDistance) { + this.currMinDistance = currMinDistance; } - @Override public String toString() { - return "Node{" + "identifier='" + identifier + '\'' + ", index=" + index + '}'; + return this.edges.toString(); + } + + public void addEdge(Edge mstEdge) { + this.edges.add(mstEdge); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Node node = (Node) o; + return isVisited == node.isVisited && edges.equals(node.edges); + } + + @Override + public int hashCode() { + return Objects.hash(edges, isVisited); } } diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java index 6466b402..ee2615dd 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java @@ -1,76 +1,164 @@ package algorithms.minimumSpanningTree.prims; -import java.util.Arrays; -import java.util.PriorityQueue; +import java.util.*; /** * Implementation of Prim's Algorithm to find MSTs * Idea: - * Starting from any source (this will be the first node to be in the MST), pick the lightest outgoing edge, and - * include the node at the other end as part of a set of nodes S. Now repeatedly do the above by picking the lightest - * outgoing edge adjacent to any node in the MST (ensure the other end of the node is not already in the MST). + * Starting from any source (this will be the first node to be in the MST), + * pick the lightest outgoing edge, and include the node at the other end as part of a set of nodes S. + * Now repeatedly do the above by picking the lightest outgoing edge adjacent to any node in S. + * (ensuring the other end of the node is not already in the MST) * Repeat until S contains all nodes in the graph. S is the MST. - * Actual implementation: - * No Edge class was implemented. Instead, the weights of the edges are stored in a 2D array adjacency matrix. - * A Node class is implemented to encapsulate a isVisited flag and the current minimum weight to reach the node. + * + * Motivating Example: Minimum Cost to Connect All Points + * + A -9- C -2- E + / / \ \ + 3 4 7 2 + / / \ / + F -1- B --5-- D +*/ + +/** + * Implementation 1: Using heap + * Time: O(V) + O(ElogV) (since heap could possibly hold E number of weights) + O(E-V) (nodes that have been 'seen' are still added to the heap, just not expanded) + O(V^2) + * Space: O(V) (hashmap to decide on MST) + O(E) (heap) = O(V+E) = O(E) */ + public class Prim { - public static int[][] getPrimsMST(Node[] nodes, int[][] adjacencyMatrix) { - PriorityQueue pq = new PriorityQueue<>((a, b) -> a.getCurrMinWeight() - b.getCurrMinWeight()); - int[][] mstMatrix = new int[nodes.length][nodes.length]; // MST adjacency matrix +// /** +// * points: Adjacency matrix that encapsulates the distance/weight between nodes +// * adjM[i][j] is the weight of the edge connecting points i and j; a value of 0 suggests there is no connection between i and j +// * @param adjM Adjacency matrix that encapsulates the distance/weight between nodes +// * @return minimum weight of the spanning tree +// */ +// public int minCostConnectPoints(int[][] adjM) { +// int v = adjM.length; +// int minCost = 0; +// Set mst = new HashSet<>(); +// mst.add(0); +// PriorityQueue pq = new PriorityQueue<>( +// (a, b) -> a.dist - b.dist +// ); +// for (int i = 0; i < v; i++) { +// if (!mst.contains(i)) { +// if (adjM[0][i] != 0) { // ensure valid edge +// pq.add(new Edge(adjM[0][i], i)); +// } +// } +// } +// while (mst.size() != v) { +// Edge popped = pq.poll(); +// if (mst.contains(popped.endNode)) { +// continue; +// } +// minCost += popped.dist; +// mst.add(popped.endNode); +// for (int i = 0; i < v; i++) { +// if (mst.contains(i)) { +// continue; +// } +// if (adjM[popped.endNode][i] != 0) { // ensure valid edge +// pq.add(new Edge(adjM[popped.endNode][i], i)); +// } +// } +// } +// return minCost; +// } +// +// /** +// * Alternative implementation that simply uses array to hold weights rather than heap. +// * Note: Starts from the node labelled 0 and repeatedly update +// * which stores the minimum weight from any node in the MST to other nodes. +// * Time: O(V) + O(V*2V) +// * Space: O(V) +// * @param adjM Adjacency matrix that encapsulates the distance/weight between nodes +// * @return minimum weight of the spanning tree +// */ +// public int minCostConnectPoints2(int[][] adjM) { +// int v = adjM.length; +// int[] weights = new int[v]; +// +// for (int i = 0; i < v; i++) { +// weights[i] = adjM[0][i]; +// } +// +// Set mst = new HashSet<>(); +// mst.add(0); // start from source 0 +// int ans = 0; +// while (mst.size() < v) { +// int next = v; +// for (int i = 0; i < v; i++) { +// if (!mst.contains(i)) { +// if (weights[i] != 0 && (next == v || weights[i] < weights[next])) { // first check for valid connection, then try to find min weight +// next = i; +// } +// } +// } +// mst.add(next); +// ans += weights[next]; +// +// for (int i = 0; i < v; i++) { +// if (!mst.contains(i)) { +// if (weights[i] == 0 || adjM[next][i] < weights[i]) { // update shortest dist to nodes that are not added to mst yet +// weights[i] = adjM[next][i]; +// } +// } +// } +// } +// return ans; +// } - // Initialize mstMatrix with all edges set to Integer.MAX_VALUE - for (int[] row : mstMatrix) { - Arrays.fill(row, Integer.MAX_VALUE); - } + public static List getPrimsMST(List graph) { + PriorityQueue pq = new PriorityQueue<>( + (a, b) -> a.getCurrMinDistance() - b.getCurrMinDistance() + ); - int[] parent = new int[nodes.length]; // To track the parent node of each node in the MST - Arrays.fill(parent, -1); // Initialize parent array with -1, indicating no parent + // Values in the map represent the corresponding node with only the edges in the MST + Map nodeToMSTNode = new HashMap<>(); - // Initialize the MST matrix to represent no edges with Integer.MAX_VALUE and 0 for self loops - for (int i = 0; i < nodes.length; i++) { - for (int j = 0; j < nodes.length; j++) { - mstMatrix[i][j] = (i == j) ? 0 : Integer.MAX_VALUE; - } - } + // mstEdge map required to track the edges in the MST. The corresponding node is the start node of the edge. + Map mstEdge = new HashMap<>(); - // Initialize all nodes' currMinWeight to infinity, except the first node - for (Node node : nodes) { - node.setCurrMinWeight(Integer.MAX_VALUE); + // Initialize each node's minDistance to infinity and add to the priority queue + for (Node node : graph) { + node.setCurrMinDistance(Integer.MAX_VALUE); pq.add(node); + nodeToMSTNode.put(node, new Node()); // Create a corresponding MST node + } + + // Assuming graph is not empty and the start node is the first node + if (!graph.isEmpty()) { + graph.get(0).setCurrMinDistance(0); } while (!pq.isEmpty()) { Node current = pq.poll(); current.setVisited(true); - int currentIndex = current.getIndex(); - - for (int i = 0; i < nodes.length; i++) { - if (adjacencyMatrix[currentIndex][i] != Integer.MAX_VALUE && !nodes[i].isVisited()) { - int weight = adjacencyMatrix[currentIndex][i]; - - if (weight < nodes[i].getCurrMinWeight()) { - pq.remove(nodes[i]); - nodes[i].setCurrMinWeight(weight); - pq.add(nodes[i]); - parent[i] = currentIndex; // Set current node as parent of adjacent node - } + for (Edge edge : current.getEdges()) { + Node adjacent = edge.getEndNode(); + if (!adjacent.isVisited() && edge.getWeight() < adjacent.getCurrMinDistance()) { + pq.remove(adjacent); + adjacent.setCurrMinDistance(edge.getWeight()); + pq.add(adjacent); + mstEdge.put(edge, current); // Update the lightest valid outgoing edge } } } - // Build MST matrix based on parent array - for (int i = 1; i < nodes.length; i++) { - int p = parent[i]; - if (p != -1) { - int weight = adjacencyMatrix[p][i]; - mstMatrix[p][i] = weight; - mstMatrix[i][p] = weight; // For undirected graphs - } + // Populate the MST nodes with the edges to be included in the MST + for (Edge edge : mstEdge.keySet()) { + Node start = mstEdge.get(edge); + nodeToMSTNode.get(start).addEdge(edge); } - return mstMatrix; + // Extract the nodes from the map to return them + return new ArrayList<>(nodeToMSTNode.values()); } + } + + From 6351ab282fcfc37de3f33cdbc9d201f5a84fdb81 Mon Sep 17 00:00:00 2001 From: junneng Date: Sun, 31 Dec 2023 22:08:29 +0800 Subject: [PATCH 41/51] Update docs for Prim's algorithm --- .../java/algorithms/minimumSpanningTree/prims/Prim.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java index ee2615dd..3169ebea 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java @@ -7,10 +7,14 @@ * Idea: * Starting from any source (this will be the first node to be in the MST), * pick the lightest outgoing edge, and include the node at the other end as part of a set of nodes S. - * Now repeatedly do the above by picking the lightest outgoing edge adjacent to any node in S. + * + * Now repeatedly do the above by picking the lightest outgoing edge adjacent to any node in the MST. * (ensuring the other end of the node is not already in the MST) * Repeat until S contains all nodes in the graph. S is the MST. * + * Actual implementation: + * + * * Motivating Example: Minimum Cost to Connect All Points * A -9- C -2- E From eb870c4c24ed031013359668c0b702fe9b9d512f Mon Sep 17 00:00:00 2001 From: junnengsoo Date: Wed, 31 Jan 2024 11:27:20 +0800 Subject: [PATCH 42/51] Remove Edge implementation, add adjacency list and identifiers --- .../minimumSpanningTree/prims/Edge.java | 24 --- .../minimumSpanningTree/prims/Node.java | 63 ++++--- .../minimumSpanningTree/prims/Prim.java | 159 +++++------------- 3 files changed, 77 insertions(+), 169 deletions(-) delete mode 100644 src/main/java/algorithms/minimumSpanningTree/prims/Edge.java diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Edge.java b/src/main/java/algorithms/minimumSpanningTree/prims/Edge.java deleted file mode 100644 index 0ca05f86..00000000 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Edge.java +++ /dev/null @@ -1,24 +0,0 @@ -package algorithms.minimumSpanningTree.prims; - -/** - * Helper class to encapsulate information about an edge; - * specifically, tells us the weight of an edge and the node on the other end - * (assumes that the starting node of the edge is known) - */ -public class Edge { - private final int weight; - private final Node endNode; - - public Edge(int weight, Node endNode) { - this.weight = weight; - this.endNode = endNode; - } - - public Node getEndNode() { - return this.endNode; - } - - public int getWeight() { - return this.weight; - } -} \ No newline at end of file diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java index 8f0d33d6..649b0a83 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java @@ -1,52 +1,59 @@ package algorithms.minimumSpanningTree.prims; -import java.util.ArrayList; -import java.util.List; +import java.util.HashMap; +import java.util.Map; import java.util.Objects; -/** - * Helper class to encapsulate information about a node; - * specifically, tells us the weight of an edge and the node on the other end - * (assumes that the starting node of the edge is known) - */ public class Node { - private final List edges; private boolean isVisited = false; - private int currMinDistance; + private int currMinWeight; + private Map adjacentNodes; + private String identifier; // Unique identifier for the node - public Node(List edges) { - this.edges = new ArrayList<>(edges); + public Node(String identifier) { + this.adjacentNodes = new HashMap<>(); + this.identifier = identifier; } - public Node() { - this.edges = new ArrayList<>(); + + public Node(String identifier, Map adjacentNodes) { + this.identifier = identifier; + this.adjacentNodes = adjacentNodes; } - public List getEdges() { - return this.edges; + public Map getAdjacentNodes() { + return adjacentNodes; } - public int getCurrMinDistance() { - return currMinDistance; + public int getCurrMinWeight() { + return currMinWeight; } - public void setVisited(boolean isVisited) { - this.isVisited = isVisited; + public void setCurrMinWeight(int currMinWeight) { + this.currMinWeight = currMinWeight; } public boolean isVisited() { return this.isVisited; } - public void setCurrMinDistance(int currMinDistance) { - this.currMinDistance = currMinDistance; + public void setVisited(boolean isVisited) { + this.isVisited = isVisited; + } + + public String getIdentifier() { + return identifier; } - public String toString() { - return this.edges.toString(); + public void setIdentifier(String identifier) { + this.identifier = identifier; } - public void addEdge(Edge mstEdge) { - this.edges.add(mstEdge); + @Override + public String toString() { + return "Node{" + + "identifier='" + identifier + '\'' + + ", adjacentNodes=" + adjacentNodes + + '}'; } @Override @@ -54,11 +61,13 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Node node = (Node) o; - return isVisited == node.isVisited && edges.equals(node.edges); + return isVisited == node.isVisited && + Objects.equals(identifier, node.identifier) && + Objects.equals(adjacentNodes, node.adjacentNodes); } @Override public int hashCode() { - return Objects.hash(edges, isVisited); + return Objects.hash(identifier, adjacentNodes, isVisited); } } diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java index 3169ebea..8c358883 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java @@ -1,11 +1,15 @@ package algorithms.minimumSpanningTree.prims; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.PriorityQueue; -/** +/** * Implementation of Prim's Algorithm to find MSTs - * Idea: - * Starting from any source (this will be the first node to be in the MST), + * Idea: + * Starting from any source (this will be the first node to be in the MST), * pick the lightest outgoing edge, and include the node at the other end as part of a set of nodes S. * * Now repeatedly do the above by picking the lightest outgoing edge adjacent to any node in the MST. @@ -16,152 +20,71 @@ * * * Motivating Example: Minimum Cost to Connect All Points - * - A -9- C -2- E - / / \ \ + * + A -9- C -2- E + / / \ \ 3 4 7 2 / / \ / - F -1- B --5-- D + F -1- B --5-- D */ - -/** - * Implementation 1: Using heap - * Time: O(V) + O(ElogV) (since heap could possibly hold E number of weights) + O(E-V) (nodes that have been 'seen' are still added to the heap, just not expanded) + O(V^2) - * Space: O(V) (hashmap to decide on MST) + O(E) (heap) = O(V+E) = O(E) - */ - public class Prim { -// /** -// * points: Adjacency matrix that encapsulates the distance/weight between nodes -// * adjM[i][j] is the weight of the edge connecting points i and j; a value of 0 suggests there is no connection between i and j -// * @param adjM Adjacency matrix that encapsulates the distance/weight between nodes -// * @return minimum weight of the spanning tree -// */ -// public int minCostConnectPoints(int[][] adjM) { -// int v = adjM.length; -// int minCost = 0; -// Set mst = new HashSet<>(); -// mst.add(0); -// PriorityQueue pq = new PriorityQueue<>( -// (a, b) -> a.dist - b.dist -// ); -// for (int i = 0; i < v; i++) { -// if (!mst.contains(i)) { -// if (adjM[0][i] != 0) { // ensure valid edge -// pq.add(new Edge(adjM[0][i], i)); -// } -// } -// } -// while (mst.size() != v) { -// Edge popped = pq.poll(); -// if (mst.contains(popped.endNode)) { -// continue; -// } -// minCost += popped.dist; -// mst.add(popped.endNode); -// for (int i = 0; i < v; i++) { -// if (mst.contains(i)) { -// continue; -// } -// if (adjM[popped.endNode][i] != 0) { // ensure valid edge -// pq.add(new Edge(adjM[popped.endNode][i], i)); -// } -// } -// } -// return minCost; -// } -// -// /** -// * Alternative implementation that simply uses array to hold weights rather than heap. -// * Note: Starts from the node labelled 0 and repeatedly update -// * which stores the minimum weight from any node in the MST to other nodes. -// * Time: O(V) + O(V*2V) -// * Space: O(V) -// * @param adjM Adjacency matrix that encapsulates the distance/weight between nodes -// * @return minimum weight of the spanning tree -// */ -// public int minCostConnectPoints2(int[][] adjM) { -// int v = adjM.length; -// int[] weights = new int[v]; -// -// for (int i = 0; i < v; i++) { -// weights[i] = adjM[0][i]; -// } -// -// Set mst = new HashSet<>(); -// mst.add(0); // start from source 0 -// int ans = 0; -// while (mst.size() < v) { -// int next = v; -// for (int i = 0; i < v; i++) { -// if (!mst.contains(i)) { -// if (weights[i] != 0 && (next == v || weights[i] < weights[next])) { // first check for valid connection, then try to find min weight -// next = i; -// } -// } -// } -// mst.add(next); -// ans += weights[next]; -// -// for (int i = 0; i < v; i++) { -// if (!mst.contains(i)) { -// if (weights[i] == 0 || adjM[next][i] < weights[i]) { // update shortest dist to nodes that are not added to mst yet -// weights[i] = adjM[next][i]; -// } -// } -// } -// } -// return ans; -// } - public static List getPrimsMST(List graph) { PriorityQueue pq = new PriorityQueue<>( - (a, b) -> a.getCurrMinDistance() - b.getCurrMinDistance() + (a, b) -> a.getCurrMinWeight() - b.getCurrMinWeight() ); // Values in the map represent the corresponding node with only the edges in the MST Map nodeToMSTNode = new HashMap<>(); + Map parentInMST = new HashMap<>(); - // mstEdge map required to track the edges in the MST. The corresponding node is the start node of the edge. - Map mstEdge = new HashMap<>(); - - // Initialize each node's minDistance to infinity and add to the priority queue + // Initialize each node's minWeight to infinity and add to the priority queue for (Node node : graph) { - node.setCurrMinDistance(Integer.MAX_VALUE); + node.setCurrMinWeight(Integer.MAX_VALUE); pq.add(node); - nodeToMSTNode.put(node, new Node()); // Create a corresponding MST node + nodeToMSTNode.put(node, new Node(node.getIdentifier())); // Create a corresponding MST node + parentInMST.put(node, null); } // Assuming graph is not empty and the start node is the first node if (!graph.isEmpty()) { - graph.get(0).setCurrMinDistance(0); + graph.get(0).setCurrMinWeight(0); } while (!pq.isEmpty()) { Node current = pq.poll(); current.setVisited(true); - for (Edge edge : current.getEdges()) { - Node adjacent = edge.getEndNode(); - if (!adjacent.isVisited() && edge.getWeight() < adjacent.getCurrMinDistance()) { - pq.remove(adjacent); - adjacent.setCurrMinDistance(edge.getWeight()); - pq.add(adjacent); - mstEdge.put(edge, current); // Update the lightest valid outgoing edge + Map currentAdjacentNodes = current.getAdjacentNodes(); + + for (Map.Entry entry : currentAdjacentNodes.entrySet()) { + Node adjacent = entry.getKey(); + Integer weight = entry.getValue(); + + if (!adjacent.isVisited() && weight < adjacent.getCurrMinWeight()) { + adjacent.setCurrMinWeight(weight); + + // Update the parent in MST + parentInMST.put(adjacent, current); } } } - // Populate the MST nodes with the edges to be included in the MST - for (Edge edge : mstEdge.keySet()) { - Node start = mstEdge.get(edge); - nodeToMSTNode.get(start).addEdge(edge); + // Construct the MST using the parent-child relationships + for (Node originalNode : graph) { + Node mstNode = nodeToMSTNode.get(originalNode); + Node parent = parentInMST.get(originalNode); + + if (parent != null) { + Node mstParent = nodeToMSTNode.get(parent); + int weight = originalNode.getAdjacentNodes().get(parent); + mstParent.getAdjacentNodes().put(mstNode, weight); + mstNode.getAdjacentNodes().put(mstParent, weight); // For undirected graphs + } } // Extract the nodes from the map to return them return new ArrayList<>(nodeToMSTNode.values()); } - } From aa63c3c66fa58498ef8ce7ab309ecda279ece3b8 Mon Sep 17 00:00:00 2001 From: junnengsoo Date: Wed, 31 Jan 2024 20:42:14 +0800 Subject: [PATCH 43/51] Add MST tests --- .../minimumSpanningTree/prims/Node.java | 7 +- .../minimumSpanningTree/prims/Prim.java | 4 +- .../minimumSpanningTree/prims/PrimsTest.java | 198 +++++++++++++----- 3 files changed, 147 insertions(+), 62 deletions(-) diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java index 649b0a83..bb91e729 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java @@ -52,7 +52,6 @@ public void setIdentifier(String identifier) { public String toString() { return "Node{" + "identifier='" + identifier + '\'' + - ", adjacentNodes=" + adjacentNodes + '}'; } @@ -61,13 +60,11 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Node node = (Node) o; - return isVisited == node.isVisited && - Objects.equals(identifier, node.identifier) && - Objects.equals(adjacentNodes, node.adjacentNodes); + return Objects.equals(identifier, node.identifier); } @Override public int hashCode() { - return Objects.hash(identifier, adjacentNodes, isVisited); + return Objects.hash(identifier); } } diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java index 8c358883..da4cfff9 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java @@ -61,7 +61,9 @@ public static List getPrimsMST(List graph) { Integer weight = entry.getValue(); if (!adjacent.isVisited() && weight < adjacent.getCurrMinWeight()) { + pq.remove(adjacent); adjacent.setCurrMinWeight(weight); + pq.add(adjacent); // Update the parent in MST parentInMST.put(adjacent, current); @@ -87,5 +89,3 @@ public static List getPrimsMST(List graph) { } } - - diff --git a/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java b/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java index 36830e82..96bc6784 100644 --- a/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java +++ b/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java @@ -1,81 +1,169 @@ package algorithms.minimumSpanningTree.prims; -import static org.junit.Assert.assertArrayEquals; - import org.junit.Test; -public class PrimsTest { +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +public class PrimsTest { @Test - public void test_simpleGraph() { - // Graph setup (Adjacency Matrix) + public void testPrimsMST_SimpleGraph() { + // Graph setup // A -1- B -1- C - int[][] adjacencyMatrix = { - {0, 1, 1}, // A: A-B, A-C - {1, 0, 1}, // B: B-A, B-C - {1, 1, 0} // C: C-A, C-B - }; - - Node[] nodes = { - new Node("A", 0), - new Node("B", 1), - new Node("C", 2) - }; + Node nodeActualA = new Node("A"); + Node nodeActualB = new Node("B"); + Node nodeActualC = new Node("C"); + + nodeActualA.getAdjacentNodes().put(nodeActualB, 1); + nodeActualB.getAdjacentNodes().put(nodeActualA, 1); + nodeActualB.getAdjacentNodes().put(nodeActualC, 1); + nodeActualC.getAdjacentNodes().put(nodeActualB, 1); + + List graph = Arrays.asList(nodeActualA, nodeActualB, nodeActualC); // Run Prim's algorithm - int[][] actualMST = Prim.getPrimsMST(nodes, adjacencyMatrix); + List actualMST = Prim.getPrimsMST(graph); // Expected MST // A -1- B -1- C - int[][] expectedMST = { - {0, 1, 1}, // A: A-B, A-C - {1, 0, Integer.MAX_VALUE}, // B: B-A - {1, Integer.MAX_VALUE, 0} // C: C-A - }; + Node nodeExpectedA = new Node("A"); + Node nodeExpectedB = new Node("B"); + Node nodeExpectedC = new Node("C"); + + nodeExpectedA.getAdjacentNodes().put(nodeExpectedB, 1); + nodeExpectedB.getAdjacentNodes().put(nodeExpectedA, 1); + nodeExpectedB.getAdjacentNodes().put(nodeExpectedC, 1); + nodeExpectedC.getAdjacentNodes().put(nodeExpectedB, 1); + + // Expected MST (same as the original graph in this simple case) + List expectedMST = Arrays.asList(nodeExpectedA, nodeExpectedB, nodeExpectedC); + + expectedMST.sort(Comparator.comparing(Node::getIdentifier)); + actualMST.sort(Comparator.comparing(Node::getIdentifier)); // Assertion - assertArrayEquals(expectedMST, actualMST); + assertGraphsEqual(expectedMST, actualMST); // Direct comparison of lists } @Test - public void test_complexGraph() { + public void testPrimsMST_ComplexGraph() { // Graph setup - // A - // / | \ - // 1 4 2 - /// | \ - //B --3-- D - // \ | / - // 2 4 3 - // \|/ - // C - int[][] adjacencyMatrix = { - {0, 1, 4, 2}, // A: A-B, A-C, A-D - {1, 0, 2, 3}, // B: B-A, B-C, B-D - {4, 2, 0, 3}, // C: C-A, C-B, C-D - {2, 3, 3, 0} // D: D-A, D-B, D-C - }; - - Node[] nodes = { - new Node("A", 0), - new Node("B", 1), - new Node("C", 2), - new Node("D", 3) - }; + // A + // / | \ + // 1 4 2 + // / | \ + // B --3-- D + // \ | / + // 2 3 3 + // \ | / + // C + Node nodeA = new Node("A"); + Node nodeB = new Node("B"); + Node nodeC = new Node("C"); + Node nodeD = new Node("D"); + + nodeA.getAdjacentNodes().put(nodeB, 1); + nodeA.getAdjacentNodes().put(nodeC, 4); + nodeA.getAdjacentNodes().put(nodeD, 2); + nodeB.getAdjacentNodes().put(nodeA, 1); + nodeB.getAdjacentNodes().put(nodeC, 3); + nodeB.getAdjacentNodes().put(nodeD, 2); + nodeC.getAdjacentNodes().put(nodeA, 4); + nodeC.getAdjacentNodes().put(nodeB, 3); + nodeC.getAdjacentNodes().put(nodeD, 3); + nodeD.getAdjacentNodes().put(nodeA, 2); + nodeD.getAdjacentNodes().put(nodeB, 2); + nodeD.getAdjacentNodes().put(nodeC, 3); + + List graph = Arrays.asList(nodeA, nodeB, nodeC, nodeD); // Run Prim's algorithm - int[][] actualMST = Prim.getPrimsMST(nodes, adjacencyMatrix); + List actualMST = Prim.getPrimsMST(graph); // Expected MST - // Based on the graph, assuming the MST is correctly computed - int[][] expectedMST = { - {0, 1, Integer.MAX_VALUE, 2}, // A: A-B, A-D - {1, 0, 2, Integer.MAX_VALUE}, // B: B-A, B-C - {Integer.MAX_VALUE, 2, 0, Integer.MAX_VALUE}, // C: C-B - {2, Integer.MAX_VALUE, Integer.MAX_VALUE, 0} // D: D-A - }; + // D -2- A -1- B -3- C + Node nodeExpectedA = new Node("A"); + Node nodeExpectedB = new Node("B"); + Node nodeExpectedC = new Node("C"); + Node nodeExpectedD = new Node("D"); + + nodeExpectedA.getAdjacentNodes().put(nodeExpectedB, 1); + nodeExpectedA.getAdjacentNodes().put(nodeExpectedD, 2); + nodeExpectedB.getAdjacentNodes().put(nodeExpectedA, 1); + nodeExpectedB.getAdjacentNodes().put(nodeExpectedC, 3); + nodeExpectedC.getAdjacentNodes().put(nodeExpectedB, 3); + nodeExpectedD.getAdjacentNodes().put(nodeExpectedA, 2); + + // Expected MST (based on the given graph) + List expectedMST = Arrays.asList(nodeExpectedA, nodeExpectedB, nodeExpectedC, nodeExpectedD); + + expectedMST.sort(Comparator.comparing(Node::getIdentifier)); + actualMST.sort(Comparator.comparing(Node::getIdentifier)); // Assertion - assertArrayEquals(expectedMST, actualMST); + assertGraphsEqual(expectedMST, actualMST); // Direct comparison of lists + } + + private void assertGraphsEqual(List expected, List actual) { + if (expected.size() != actual.size()) { + fail("The MSTs do not have the same number of nodes. Expected size: " + + expected.size() + ", Actual size: " + actual.size()); + } + for (int i = 0; i < expected.size(); i++) { + Node expectedNode = expected.get(i); + Node actualNode = actual.get(i); + assertTrue("Nodes do not match at index " + i + ": Expected " + + expectedNode + ", Actual " + actualNode, + nodesAreEqual(expectedNode, actualNode)); + } + } + + private boolean nodesAreEqual(Node node1, Node node2) { + if (!node1.getIdentifier().equals(node2.getIdentifier())) { + fail("Node identifiers do not match: Expected " + + node1.getIdentifier() + ", Actual " + node2.getIdentifier()); + } + if (!nodesHaveSameEdges(node1, node2)) { + fail("Adjacent nodes do not match for Node " + node1.getIdentifier()); + } + return true; + } + + private boolean nodesHaveSameEdges(Node node1, Node node2) { + Map adj1 = node1.getAdjacentNodes(); + Map adj2 = node2.getAdjacentNodes(); + if (adj1.size() != adj2.size()) { + fail("Different number of adjacent nodes for Node " + node1.getIdentifier() + + ". Expected size: " + adj1.size() + ", Actual size: " + adj2.size()); + } + for (Map.Entry entry : adj1.entrySet()) { + Node key = findNodeById(adj2.keySet(), entry.getKey().getIdentifier()); + if (key == null) { + fail("Missing adjacent node '" + entry.getKey().getIdentifier() + + "' in Node " + node1.getIdentifier()); + } + if (!adj2.get(key).equals(entry.getValue())) { + fail("Edge weight does not match for edge " + node1.getIdentifier() + + "-" + key.getIdentifier() + ". Expected weight: " + + entry.getValue() + ", Actual weight: " + adj2.get(key)); + } + } + return true; + } + + + private Node findNodeById(Set nodes, String id) { + for (Node node : nodes) { + if (node.getIdentifier().equals(id)) { + return node; + } + } + return null; } } From be51a19d86f1ae1804796e3de0fc6108aa0526fd Mon Sep 17 00:00:00 2001 From: junnengsoo Date: Wed, 31 Jan 2024 21:22:35 +0800 Subject: [PATCH 44/51] Resolve stylecheck --- .../minimumSpanningTree/prims/Node.java | 39 +++++++++++++++---- .../minimumSpanningTree/prims/Prim.java | 31 +++++---------- .../minimumSpanningTree/prims/PrimsTest.java | 10 ++--- 3 files changed, 46 insertions(+), 34 deletions(-) diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java index bb91e729..2219e5e3 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java @@ -4,17 +4,33 @@ import java.util.Map; import java.util.Objects; +/** + * Node class for Prim's algorithm. + * + * Each node has a unique identifier and contains a Map of adjacent nodes and their corresponding edge weights. + */ public class Node { private boolean isVisited = false; - private int currMinWeight; - private Map adjacentNodes; - private String identifier; // Unique identifier for the node + private int currMinWeight; // Current minimum weight to get to this node to calculate Prim's MST + private final Map adjacentNodes; + private String identifier; + /** + * Constructor for a node with no adjacent nodes. + * + * @param identifier Unique identifier for the node + */ public Node(String identifier) { this.adjacentNodes = new HashMap<>(); this.identifier = identifier; } + /** + * Constructor for a node with a list of adjacent nodes. + * + * @param identifier Unique identifier for the node + * @param adjacentNodes List of adjacent nodes + */ public Node(String identifier, Map adjacentNodes) { this.identifier = identifier; this.adjacentNodes = adjacentNodes; @@ -50,15 +66,22 @@ public void setIdentifier(String identifier) { @Override public String toString() { - return "Node{" + - "identifier='" + identifier + '\'' + - '}'; + return "Node{" + + "identifier='" + + identifier + '\'' + + '}'; } @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + + if (o == null || getClass() != o.getClass()) { + return false; + } + Node node = (Node) o; return Objects.equals(identifier, node.identifier); } diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java index da4cfff9..6a6cf7d5 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java @@ -6,32 +6,21 @@ import java.util.Map; import java.util.PriorityQueue; -/** +/** * Implementation of Prim's Algorithm to find MSTs - * Idea: - * Starting from any source (this will be the first node to be in the MST), - * pick the lightest outgoing edge, and include the node at the other end as part of a set of nodes S. - * - * Now repeatedly do the above by picking the lightest outgoing edge adjacent to any node in the MST. - * (ensuring the other end of the node is not already in the MST) + * Idea: + * Starting from any source (this will be the first node to be in the MST), pick the lightest outgoing edge, and + * include the node at the other end as part of a set of nodes S. Now repeatedly do the above by picking the lightest + * outgoing edge adjacent to any node in the MST (ensure the other end of the node is not already in the MST). * Repeat until S contains all nodes in the graph. S is the MST. - * * Actual implementation: - * - * - * Motivating Example: Minimum Cost to Connect All Points - * - A -9- C -2- E - / / \ \ - 3 4 7 2 - / / \ / - F -1- B --5-- D -*/ + * No Edge class was implemented. Instead, each node has a Map of adjacent nodes and their corresponding edge weights. + * To represent the MST, a new list of nodes is created with the same identifiers as the original graph, with each node + * containing only the edges in the MST. + */ public class Prim { public static List getPrimsMST(List graph) { - PriorityQueue pq = new PriorityQueue<>( - (a, b) -> a.getCurrMinWeight() - b.getCurrMinWeight() - ); + PriorityQueue pq = new PriorityQueue<>((a, b) -> a.getCurrMinWeight() - b.getCurrMinWeight()); // Values in the map represent the corresponding node with only the edges in the MST Map nodeToMSTNode = new HashMap<>(); diff --git a/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java b/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java index 96bc6784..31127790 100644 --- a/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java +++ b/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java @@ -1,6 +1,7 @@ package algorithms.minimumSpanningTree.prims; -import org.junit.Test; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.util.Arrays; import java.util.Comparator; @@ -8,12 +9,11 @@ import java.util.Map; import java.util.Set; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; +import org.junit.Test; public class PrimsTest { @Test - public void testPrimsMST_SimpleGraph() { + public void test_simpleGraph() { // Graph setup // A -1- B -1- C Node nodeActualA = new Node("A"); @@ -52,7 +52,7 @@ public void testPrimsMST_SimpleGraph() { } @Test - public void testPrimsMST_ComplexGraph() { + public void test_complexGraph() { // Graph setup // A // / | \ From 50f4836c31026abb474adb47ba11a2ca17538d07 Mon Sep 17 00:00:00 2001 From: junnengsoo Date: Tue, 26 Mar 2024 20:22:34 +0800 Subject: [PATCH 45/51] Use adjacency matrix instead of hash map for tracking of nodes --- .../minimumSpanningTree/prims/Node.java | 70 ++++++------------- .../minimumSpanningTree/prims/Prim.java | 63 ++++++----------- 2 files changed, 45 insertions(+), 88 deletions(-) diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java index 2219e5e3..c149e68e 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java @@ -1,45 +1,19 @@ package algorithms.minimumSpanningTree.prims; -import java.util.HashMap; -import java.util.Map; import java.util.Objects; -/** - * Node class for Prim's algorithm. - * - * Each node has a unique identifier and contains a Map of adjacent nodes and their corresponding edge weights. - */ public class Node { private boolean isVisited = false; - private int currMinWeight; // Current minimum weight to get to this node to calculate Prim's MST - private final Map adjacentNodes; + private int currMinWeight = Integer.MAX_VALUE; // Current minimum weight to get to this node + private int index; // Index of this node in the adjacency matrix private String identifier; - /** - * Constructor for a node with no adjacent nodes. - * - * @param identifier Unique identifier for the node - */ - public Node(String identifier) { - this.adjacentNodes = new HashMap<>(); + public Node(String identifier, int index) { this.identifier = identifier; + this.index = index; } - /** - * Constructor for a node with a list of adjacent nodes. - * - * @param identifier Unique identifier for the node - * @param adjacentNodes List of adjacent nodes - */ - public Node(String identifier, Map adjacentNodes) { - this.identifier = identifier; - this.adjacentNodes = adjacentNodes; - } - - public Map getAdjacentNodes() { - return adjacentNodes; - } - + // Getter and setter for currMinWeight public int getCurrMinWeight() { return currMinWeight; } @@ -48,46 +22,46 @@ public void setCurrMinWeight(int currMinWeight) { this.currMinWeight = currMinWeight; } + // Getter and setter for isVisited public boolean isVisited() { - return this.isVisited; + return isVisited; } public void setVisited(boolean isVisited) { this.isVisited = isVisited; } + // Getter for identifier public String getIdentifier() { return identifier; } - public void setIdentifier(String identifier) { - this.identifier = identifier; + // Getter and setter for index + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; } + // toString method @Override public String toString() { - return "Node{" - + "identifier='" - + identifier + '\'' - + '}'; + return "Node{" + "identifier='" + identifier + '\'' + ", index=" + index + '}'; } + // equals and hashCode based on identifier and index @Override public boolean equals(Object o) { - if (this == o) { - return true; - } - - if (o == null || getClass() != o.getClass()) { - return false; - } - + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; Node node = (Node) o; - return Objects.equals(identifier, node.identifier); + return index == node.index && Objects.equals(identifier, node.identifier); } @Override public int hashCode() { - return Objects.hash(identifier); + return Objects.hash(identifier, index); } } diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java index 6a6cf7d5..f5ec6752 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java @@ -19,62 +19,45 @@ * containing only the edges in the MST. */ public class Prim { - public static List getPrimsMST(List graph) { + public static int[][] getPrimsMST(Node[] nodes, int[][] adjacencyMatrix) { PriorityQueue pq = new PriorityQueue<>((a, b) -> a.getCurrMinWeight() - b.getCurrMinWeight()); + int[][] mstMatrix = new int[nodes.length][nodes.length]; // MST adjacency matrix - // Values in the map represent the corresponding node with only the edges in the MST - Map nodeToMSTNode = new HashMap<>(); - Map parentInMST = new HashMap<>(); + // Initialize the MST matrix to represent no edges with Integer.MAX_VALUE + for (int i = 0; i < nodes.length; i++) { + for (int j = 0; j < nodes.length; j++) { + mstMatrix[i][j] = Integer.MAX_VALUE; + } + } - // Initialize each node's minWeight to infinity and add to the priority queue - for (Node node : graph) { + // Initialize all nodes' currMinWeight to infinity, except the first node + for (Node node : nodes) { node.setCurrMinWeight(Integer.MAX_VALUE); pq.add(node); - nodeToMSTNode.put(node, new Node(node.getIdentifier())); // Create a corresponding MST node - parentInMST.put(node, null); - } - - // Assuming graph is not empty and the start node is the first node - if (!graph.isEmpty()) { - graph.get(0).setCurrMinWeight(0); } while (!pq.isEmpty()) { Node current = pq.poll(); current.setVisited(true); - Map currentAdjacentNodes = current.getAdjacentNodes(); - - for (Map.Entry entry : currentAdjacentNodes.entrySet()) { - Node adjacent = entry.getKey(); - Integer weight = entry.getValue(); + int currentIndex = current.getIndex(); - if (!adjacent.isVisited() && weight < adjacent.getCurrMinWeight()) { - pq.remove(adjacent); - adjacent.setCurrMinWeight(weight); - pq.add(adjacent); + for (int i = 0; i < nodes.length; i++) { + if (adjacencyMatrix[currentIndex][i] != Integer.MAX_VALUE && !nodes[i].isVisited()) { + int weight = adjacencyMatrix[currentIndex][i]; - // Update the parent in MST - parentInMST.put(adjacent, current); + if (weight < nodes[i].getCurrMinWeight()) { + pq.remove(nodes[i]); + nodes[i].setCurrMinWeight(weight); + pq.add(nodes[i]); + // Update the MST matrix + mstMatrix[currentIndex][i] = weight; + mstMatrix[i][currentIndex] = weight; // For undirected graphs + } } } } - - // Construct the MST using the parent-child relationships - for (Node originalNode : graph) { - Node mstNode = nodeToMSTNode.get(originalNode); - Node parent = parentInMST.get(originalNode); - - if (parent != null) { - Node mstParent = nodeToMSTNode.get(parent); - int weight = originalNode.getAdjacentNodes().get(parent); - mstParent.getAdjacentNodes().put(mstNode, weight); - mstNode.getAdjacentNodes().put(mstParent, weight); // For undirected graphs - } - } - - // Extract the nodes from the map to return them - return new ArrayList<>(nodeToMSTNode.values()); + return mstMatrix; } } From 484b676c67f6ea4c82dadd3d56ce6dfea39c7b92 Mon Sep 17 00:00:00 2001 From: junnengsoo Date: Tue, 26 Mar 2024 22:42:32 +0800 Subject: [PATCH 46/51] Add adjacency matrix and new test cases --- .../minimumSpanningTree/prims/Node.java | 48 ++--- .../minimumSpanningTree/prims/Prim.java | 37 ++-- .../minimumSpanningTree/prims/PrimsTest.java | 192 +++++------------- 3 files changed, 101 insertions(+), 176 deletions(-) diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java index c149e68e..de39584d 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java @@ -2,18 +2,28 @@ import java.util.Objects; +/** + * Node class to represent a node in the graph + */ public class Node { private boolean isVisited = false; private int currMinWeight = Integer.MAX_VALUE; // Current minimum weight to get to this node private int index; // Index of this node in the adjacency matrix - private String identifier; + private final String identifier; + /** + * Constructor + * @param identifier + * @param index + */ public Node(String identifier, int index) { this.identifier = identifier; this.index = index; } - // Getter and setter for currMinWeight + /** + * Getter and setter for currMinWeight + */ public int getCurrMinWeight() { return currMinWeight; } @@ -22,21 +32,26 @@ public void setCurrMinWeight(int currMinWeight) { this.currMinWeight = currMinWeight; } - // Getter and setter for isVisited + /** + * Getter for identifier + * @return identifier + */ public boolean isVisited() { return isVisited; } + /** + * Setter for isVisited + * @param isVisited + */ public void setVisited(boolean isVisited) { this.isVisited = isVisited; } - // Getter for identifier - public String getIdentifier() { - return identifier; - } - - // Getter and setter for index + /** + * Getter for identifier + * @return identifier + */ public int getIndex() { return index; } @@ -45,23 +60,8 @@ public void setIndex(int index) { this.index = index; } - // toString method @Override public String toString() { return "Node{" + "identifier='" + identifier + '\'' + ", index=" + index + '}'; } - - // equals and hashCode based on identifier and index - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Node node = (Node) o; - return index == node.index && Objects.equals(identifier, node.identifier); - } - - @Override - public int hashCode() { - return Objects.hash(identifier, index); - } } diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java index f5ec6752..6466b402 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java @@ -1,9 +1,6 @@ package algorithms.minimumSpanningTree.prims; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.Arrays; import java.util.PriorityQueue; /** @@ -14,19 +11,26 @@ * outgoing edge adjacent to any node in the MST (ensure the other end of the node is not already in the MST). * Repeat until S contains all nodes in the graph. S is the MST. * Actual implementation: - * No Edge class was implemented. Instead, each node has a Map of adjacent nodes and their corresponding edge weights. - * To represent the MST, a new list of nodes is created with the same identifiers as the original graph, with each node - * containing only the edges in the MST. + * No Edge class was implemented. Instead, the weights of the edges are stored in a 2D array adjacency matrix. + * A Node class is implemented to encapsulate a isVisited flag and the current minimum weight to reach the node. */ public class Prim { public static int[][] getPrimsMST(Node[] nodes, int[][] adjacencyMatrix) { PriorityQueue pq = new PriorityQueue<>((a, b) -> a.getCurrMinWeight() - b.getCurrMinWeight()); int[][] mstMatrix = new int[nodes.length][nodes.length]; // MST adjacency matrix - // Initialize the MST matrix to represent no edges with Integer.MAX_VALUE + // Initialize mstMatrix with all edges set to Integer.MAX_VALUE + for (int[] row : mstMatrix) { + Arrays.fill(row, Integer.MAX_VALUE); + } + + int[] parent = new int[nodes.length]; // To track the parent node of each node in the MST + Arrays.fill(parent, -1); // Initialize parent array with -1, indicating no parent + + // Initialize the MST matrix to represent no edges with Integer.MAX_VALUE and 0 for self loops for (int i = 0; i < nodes.length; i++) { for (int j = 0; j < nodes.length; j++) { - mstMatrix[i][j] = Integer.MAX_VALUE; + mstMatrix[i][j] = (i == j) ? 0 : Integer.MAX_VALUE; } } @@ -50,13 +54,22 @@ public static int[][] getPrimsMST(Node[] nodes, int[][] adjacencyMatrix) { pq.remove(nodes[i]); nodes[i].setCurrMinWeight(weight); pq.add(nodes[i]); - // Update the MST matrix - mstMatrix[currentIndex][i] = weight; - mstMatrix[i][currentIndex] = weight; // For undirected graphs + parent[i] = currentIndex; // Set current node as parent of adjacent node } } } } + + // Build MST matrix based on parent array + for (int i = 1; i < nodes.length; i++) { + int p = parent[i]; + if (p != -1) { + int weight = adjacencyMatrix[p][i]; + mstMatrix[p][i] = weight; + mstMatrix[i][p] = weight; // For undirected graphs + } + } + return mstMatrix; } } diff --git a/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java b/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java index 31127790..36830e82 100644 --- a/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java +++ b/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java @@ -1,169 +1,81 @@ package algorithms.minimumSpanningTree.prims; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.Arrays; -import java.util.Comparator; -import java.util.List; -import java.util.Map; -import java.util.Set; +import static org.junit.Assert.assertArrayEquals; import org.junit.Test; public class PrimsTest { + @Test public void test_simpleGraph() { - // Graph setup + // Graph setup (Adjacency Matrix) // A -1- B -1- C - Node nodeActualA = new Node("A"); - Node nodeActualB = new Node("B"); - Node nodeActualC = new Node("C"); - - nodeActualA.getAdjacentNodes().put(nodeActualB, 1); - nodeActualB.getAdjacentNodes().put(nodeActualA, 1); - nodeActualB.getAdjacentNodes().put(nodeActualC, 1); - nodeActualC.getAdjacentNodes().put(nodeActualB, 1); - - List graph = Arrays.asList(nodeActualA, nodeActualB, nodeActualC); + int[][] adjacencyMatrix = { + {0, 1, 1}, // A: A-B, A-C + {1, 0, 1}, // B: B-A, B-C + {1, 1, 0} // C: C-A, C-B + }; + + Node[] nodes = { + new Node("A", 0), + new Node("B", 1), + new Node("C", 2) + }; // Run Prim's algorithm - List actualMST = Prim.getPrimsMST(graph); + int[][] actualMST = Prim.getPrimsMST(nodes, adjacencyMatrix); // Expected MST // A -1- B -1- C - Node nodeExpectedA = new Node("A"); - Node nodeExpectedB = new Node("B"); - Node nodeExpectedC = new Node("C"); - - nodeExpectedA.getAdjacentNodes().put(nodeExpectedB, 1); - nodeExpectedB.getAdjacentNodes().put(nodeExpectedA, 1); - nodeExpectedB.getAdjacentNodes().put(nodeExpectedC, 1); - nodeExpectedC.getAdjacentNodes().put(nodeExpectedB, 1); - - // Expected MST (same as the original graph in this simple case) - List expectedMST = Arrays.asList(nodeExpectedA, nodeExpectedB, nodeExpectedC); - - expectedMST.sort(Comparator.comparing(Node::getIdentifier)); - actualMST.sort(Comparator.comparing(Node::getIdentifier)); + int[][] expectedMST = { + {0, 1, 1}, // A: A-B, A-C + {1, 0, Integer.MAX_VALUE}, // B: B-A + {1, Integer.MAX_VALUE, 0} // C: C-A + }; // Assertion - assertGraphsEqual(expectedMST, actualMST); // Direct comparison of lists + assertArrayEquals(expectedMST, actualMST); } @Test public void test_complexGraph() { // Graph setup - // A - // / | \ - // 1 4 2 - // / | \ - // B --3-- D - // \ | / - // 2 3 3 - // \ | / - // C - Node nodeA = new Node("A"); - Node nodeB = new Node("B"); - Node nodeC = new Node("C"); - Node nodeD = new Node("D"); - - nodeA.getAdjacentNodes().put(nodeB, 1); - nodeA.getAdjacentNodes().put(nodeC, 4); - nodeA.getAdjacentNodes().put(nodeD, 2); - nodeB.getAdjacentNodes().put(nodeA, 1); - nodeB.getAdjacentNodes().put(nodeC, 3); - nodeB.getAdjacentNodes().put(nodeD, 2); - nodeC.getAdjacentNodes().put(nodeA, 4); - nodeC.getAdjacentNodes().put(nodeB, 3); - nodeC.getAdjacentNodes().put(nodeD, 3); - nodeD.getAdjacentNodes().put(nodeA, 2); - nodeD.getAdjacentNodes().put(nodeB, 2); - nodeD.getAdjacentNodes().put(nodeC, 3); - - List graph = Arrays.asList(nodeA, nodeB, nodeC, nodeD); + // A + // / | \ + // 1 4 2 + /// | \ + //B --3-- D + // \ | / + // 2 4 3 + // \|/ + // C + int[][] adjacencyMatrix = { + {0, 1, 4, 2}, // A: A-B, A-C, A-D + {1, 0, 2, 3}, // B: B-A, B-C, B-D + {4, 2, 0, 3}, // C: C-A, C-B, C-D + {2, 3, 3, 0} // D: D-A, D-B, D-C + }; + + Node[] nodes = { + new Node("A", 0), + new Node("B", 1), + new Node("C", 2), + new Node("D", 3) + }; // Run Prim's algorithm - List actualMST = Prim.getPrimsMST(graph); + int[][] actualMST = Prim.getPrimsMST(nodes, adjacencyMatrix); // Expected MST - // D -2- A -1- B -3- C - Node nodeExpectedA = new Node("A"); - Node nodeExpectedB = new Node("B"); - Node nodeExpectedC = new Node("C"); - Node nodeExpectedD = new Node("D"); - - nodeExpectedA.getAdjacentNodes().put(nodeExpectedB, 1); - nodeExpectedA.getAdjacentNodes().put(nodeExpectedD, 2); - nodeExpectedB.getAdjacentNodes().put(nodeExpectedA, 1); - nodeExpectedB.getAdjacentNodes().put(nodeExpectedC, 3); - nodeExpectedC.getAdjacentNodes().put(nodeExpectedB, 3); - nodeExpectedD.getAdjacentNodes().put(nodeExpectedA, 2); - - // Expected MST (based on the given graph) - List expectedMST = Arrays.asList(nodeExpectedA, nodeExpectedB, nodeExpectedC, nodeExpectedD); - - expectedMST.sort(Comparator.comparing(Node::getIdentifier)); - actualMST.sort(Comparator.comparing(Node::getIdentifier)); + // Based on the graph, assuming the MST is correctly computed + int[][] expectedMST = { + {0, 1, Integer.MAX_VALUE, 2}, // A: A-B, A-D + {1, 0, 2, Integer.MAX_VALUE}, // B: B-A, B-C + {Integer.MAX_VALUE, 2, 0, Integer.MAX_VALUE}, // C: C-B + {2, Integer.MAX_VALUE, Integer.MAX_VALUE, 0} // D: D-A + }; // Assertion - assertGraphsEqual(expectedMST, actualMST); // Direct comparison of lists - } - - private void assertGraphsEqual(List expected, List actual) { - if (expected.size() != actual.size()) { - fail("The MSTs do not have the same number of nodes. Expected size: " - + expected.size() + ", Actual size: " + actual.size()); - } - for (int i = 0; i < expected.size(); i++) { - Node expectedNode = expected.get(i); - Node actualNode = actual.get(i); - assertTrue("Nodes do not match at index " + i + ": Expected " - + expectedNode + ", Actual " + actualNode, - nodesAreEqual(expectedNode, actualNode)); - } - } - - private boolean nodesAreEqual(Node node1, Node node2) { - if (!node1.getIdentifier().equals(node2.getIdentifier())) { - fail("Node identifiers do not match: Expected " - + node1.getIdentifier() + ", Actual " + node2.getIdentifier()); - } - if (!nodesHaveSameEdges(node1, node2)) { - fail("Adjacent nodes do not match for Node " + node1.getIdentifier()); - } - return true; - } - - private boolean nodesHaveSameEdges(Node node1, Node node2) { - Map adj1 = node1.getAdjacentNodes(); - Map adj2 = node2.getAdjacentNodes(); - if (adj1.size() != adj2.size()) { - fail("Different number of adjacent nodes for Node " + node1.getIdentifier() - + ". Expected size: " + adj1.size() + ", Actual size: " + adj2.size()); - } - for (Map.Entry entry : adj1.entrySet()) { - Node key = findNodeById(adj2.keySet(), entry.getKey().getIdentifier()); - if (key == null) { - fail("Missing adjacent node '" + entry.getKey().getIdentifier() - + "' in Node " + node1.getIdentifier()); - } - if (!adj2.get(key).equals(entry.getValue())) { - fail("Edge weight does not match for edge " + node1.getIdentifier() - + "-" + key.getIdentifier() + ". Expected weight: " - + entry.getValue() + ", Actual weight: " + adj2.get(key)); - } - } - return true; - } - - - private Node findNodeById(Set nodes, String id) { - for (Node node : nodes) { - if (node.getIdentifier().equals(id)) { - return node; - } - } - return null; + assertArrayEquals(expectedMST, actualMST); } } From f552c24c88873a813fb517078acac146947a81b0 Mon Sep 17 00:00:00 2001 From: junnengsoo Date: Wed, 27 Mar 2024 16:20:47 +0800 Subject: [PATCH 47/51] Add README --- .../minimumSpanningTree/prims/Node.java | 46 ++++++++----------- .../minimumSpanningTree/prims/Prim.java | 29 +++++++----- .../minimumSpanningTree/prims/README.md | 39 ++++++++++++++-- .../minimumSpanningTree/prims/PrimsTest.java | 28 ++++++----- 4 files changed, 88 insertions(+), 54 deletions(-) diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java index de39584d..fb465f00 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Node.java @@ -1,24 +1,36 @@ package algorithms.minimumSpanningTree.prims; -import java.util.Objects; - /** * Node class to represent a node in the graph + * Note: In our Node class, we do not allow the currMinWeight to be updated after initialization to prevent any + * reference issues in the PriorityQueue. */ public class Node { - private boolean isVisited = false; - private int currMinWeight = Integer.MAX_VALUE; // Current minimum weight to get to this node + private final int currMinWeight; // Current minimum weight to get to this node private int index; // Index of this node in the adjacency matrix private final String identifier; /** - * Constructor + * Constructor for Node + * @param identifier + * @param index + * @param currMinWeight + */ + public Node(String identifier, int index, int currMinWeight) { + this.identifier = identifier; + this.index = index; + this.currMinWeight = currMinWeight; + } + + /** + * Constructor for Node with default currMinWeight * @param identifier * @param index */ public Node(String identifier, int index) { this.identifier = identifier; this.index = index; + this.currMinWeight = Integer.MAX_VALUE; } /** @@ -28,38 +40,18 @@ public int getCurrMinWeight() { return currMinWeight; } - public void setCurrMinWeight(int currMinWeight) { - this.currMinWeight = currMinWeight; - } - /** * Getter for identifier * @return identifier */ - public boolean isVisited() { - return isVisited; - } - - /** - * Setter for isVisited - * @param isVisited - */ - public void setVisited(boolean isVisited) { - this.isVisited = isVisited; + public String getIdentifier() { + return identifier; } - /** - * Getter for identifier - * @return identifier - */ public int getIndex() { return index; } - public void setIndex(int index) { - this.index = index; - } - @Override public String toString() { return "Node{" + "identifier='" + identifier + '\'' + ", index=" + index + '}'; diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java index 6466b402..9b59dce0 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java +++ b/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java @@ -11,8 +11,9 @@ * outgoing edge adjacent to any node in the MST (ensure the other end of the node is not already in the MST). * Repeat until S contains all nodes in the graph. S is the MST. * Actual implementation: - * No Edge class was implemented. Instead, the weights of the edges are stored in a 2D array adjacency matrix. - * A Node class is implemented to encapsulate a isVisited flag and the current minimum weight to reach the node. + * No Edge class was implemented. Instead, the weights of the edges are stored in a 2D array adjacency matrix. An + * adjacency list may be used instead + * A Node class is implemented to encapsulate the current minimum weight to reach the node. */ public class Prim { public static int[][] getPrimsMST(Node[] nodes, int[][] adjacencyMatrix) { @@ -27,6 +28,9 @@ public static int[][] getPrimsMST(Node[] nodes, int[][] adjacencyMatrix) { int[] parent = new int[nodes.length]; // To track the parent node of each node in the MST Arrays.fill(parent, -1); // Initialize parent array with -1, indicating no parent + boolean[] visited = new boolean[nodes.length]; // To track visited nodes + Arrays.fill(visited, false); // Initialize visited array with false, indicating not visited + // Initialize the MST matrix to represent no edges with Integer.MAX_VALUE and 0 for self loops for (int i = 0; i < nodes.length; i++) { for (int j = 0; j < nodes.length; j++) { @@ -34,27 +38,28 @@ public static int[][] getPrimsMST(Node[] nodes, int[][] adjacencyMatrix) { } } - // Initialize all nodes' currMinWeight to infinity, except the first node - for (Node node : nodes) { - node.setCurrMinWeight(Integer.MAX_VALUE); - pq.add(node); - } + // Add all nodes to the priority queue, with each node's curr min weight already set to Integer.MAX_VALUE + pq.addAll(Arrays.asList(nodes)); while (!pq.isEmpty()) { Node current = pq.poll(); - current.setVisited(true); int currentIndex = current.getIndex(); + if (visited[currentIndex]) { // Skip if node is already visited + continue; + } + + visited[currentIndex] = true; + for (int i = 0; i < nodes.length; i++) { - if (adjacencyMatrix[currentIndex][i] != Integer.MAX_VALUE && !nodes[i].isVisited()) { + if (adjacencyMatrix[currentIndex][i] != Integer.MAX_VALUE && !visited[nodes[i].getIndex()]) { int weight = adjacencyMatrix[currentIndex][i]; if (weight < nodes[i].getCurrMinWeight()) { - pq.remove(nodes[i]); - nodes[i].setCurrMinWeight(weight); - pq.add(nodes[i]); + Node newNode = new Node(nodes[i].getIdentifier(), nodes[i].getIndex(), weight); parent[i] = currentIndex; // Set current node as parent of adjacent node + pq.add(newNode); } } } diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/README.md b/src/main/java/algorithms/minimumSpanningTree/prims/README.md index f99d3025..50062a5b 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/README.md +++ b/src/main/java/algorithms/minimumSpanningTree/prims/README.md @@ -3,11 +3,44 @@ ## Background Prim's Algorithm is a greedy algorithm that finds the minimum spanning tree of a graph by starting from an -arbitrary node (vertex) and adding the edge with the minimum weight that connects the current tree to a new node, adding -the node to the current tree, until all nodes are included in the tree. +arbitrary node (vertex) and adding the edge, with the minimum weight that connects the current tree to an unexplored +node, and the unexplored node to the current tree, until all nodes are included in the tree. + +### Implementation Details + +A priority queue (binary heap) is utilised to keep track of the minimum weight edge that connects the current tree to an +unexplored node. In an ideal scenario, the minimum weight edge to each node in the priority queue should be updated each +time a lighter edge is found to maintain a single unique node in the priority queue. This means that a decrease key +operation is required. However, we know that the decrease key operation of a binary heap implementation of a priority +queue will take O(V) time, which will result in a larger time complexity for the entire algorithm compared to using only +O(log V) operations for each edge. + +Hence, in our implementation, to avoid the use of a decrease key operation, we will simply insert duplicate nodes with +their new minimum weight edge, which will take O(log E) = O(log V) given an upper bound of E = V^2, into the queue, +while leaving the old node in the queue. Additionally, we will track if a node has already been added into the MST to +avoid adding duplicate nodes. + +Note that a priority queue is an abstract data type that can be implemented using different data structures. In this +implementation, the default Java `PriorityQueue` is used, which is a binary heap. By implementing the priority queue +with an AVL tree, a decrease key operation that has a time complexity of O(log V) can also be achieved. ## Complexity Analysis +**Time Complexity:** +- O(V^2 log V) for the basic version with an adjacency matrix, where V is the number of vertices. +- O(E log V) with a binary heap and adjacency list, where V and E is the number of vertices and edges +respectively. + +**Space Complexity:** +- O(V^2) for the adjacency matrix representation. +- O(V + E) for the adjacency list representation. + ## Notes -### Difference between Prim's Algorithm and Dijkstra's Algorithm \ No newline at end of file +### Difference between Prim's Algorithm and Dijkstra's Algorithm + +| | Prim's Algorithm | Dijkstra's Algorithm | +|-------------------------------------|---------------------------------------------------------------------------------|----------------------------------------------------------| +| Purpose | Finds MST - minimum sum of edge weights that includes all vertices in the graph | Finds shortest path from a single source to all vertices | +| Property Compared in Priority Queue | Minimum weight of incoming edge to a vertex | Minimum distance from source vertex to current vertex | + diff --git a/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java b/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java index 36830e82..f54ddbfa 100644 --- a/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java +++ b/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java @@ -9,7 +9,11 @@ public class PrimsTest { @Test public void test_simpleGraph() { // Graph setup (Adjacency Matrix) - // A -1- B -1- C + // B + // / \ + // 1 1 + // / \ + // A - 1 - C int[][] adjacencyMatrix = { {0, 1, 1}, // A: A-B, A-C {1, 0, 1}, // B: B-A, B-C @@ -28,9 +32,9 @@ public void test_simpleGraph() { // Expected MST // A -1- B -1- C int[][] expectedMST = { - {0, 1, 1}, // A: A-B, A-C - {1, 0, Integer.MAX_VALUE}, // B: B-A - {1, Integer.MAX_VALUE, 0} // C: C-A + {0, 1, Integer.MAX_VALUE}, // A: A-B + {1, 0, 1}, // B: B-A, B-C + {Integer.MAX_VALUE, 1, 0} // C: C-B }; // Assertion @@ -42,18 +46,18 @@ public void test_complexGraph() { // Graph setup // A // / | \ - // 1 4 2 + // 1 4 3 /// | \ //B --3-- D // \ | / - // 2 4 3 + // 2 4 1 // \|/ // C int[][] adjacencyMatrix = { - {0, 1, 4, 2}, // A: A-B, A-C, A-D + {0, 1, 4, 3}, // A: A-B, A-C, A-D {1, 0, 2, 3}, // B: B-A, B-C, B-D - {4, 2, 0, 3}, // C: C-A, C-B, C-D - {2, 3, 3, 0} // D: D-A, D-B, D-C + {4, 2, 0, 1}, // C: C-A, C-B, C-D + {3, 3, 1, 0} // D: D-A, D-B, D-C }; Node[] nodes = { @@ -69,10 +73,10 @@ public void test_complexGraph() { // Expected MST // Based on the graph, assuming the MST is correctly computed int[][] expectedMST = { - {0, 1, Integer.MAX_VALUE, 2}, // A: A-B, A-D + {0, 1, Integer.MAX_VALUE, Integer.MAX_VALUE}, // A: A-B {1, 0, 2, Integer.MAX_VALUE}, // B: B-A, B-C - {Integer.MAX_VALUE, 2, 0, Integer.MAX_VALUE}, // C: C-B - {2, Integer.MAX_VALUE, Integer.MAX_VALUE, 0} // D: D-A + {Integer.MAX_VALUE, 2, 0, 1}, // C: C-B, C-D + {Integer.MAX_VALUE, Integer.MAX_VALUE, 1, 0} // D: D-C }; // Assertion From 54d65365a9cee4e5ccd2ded674de2372d26eb1ba Mon Sep 17 00:00:00 2001 From: junnengsoo Date: Wed, 27 Mar 2024 19:35:22 +0800 Subject: [PATCH 48/51] Add Kruskal's implementation and tests less README --- .../algorithms/minimumSpanningTree/README.md | 2 +- .../kruskal/DisjointSet.java | 59 +++++++++++++ .../minimumSpanningTree/kruskal/Edge.java | 36 ++++++++ .../minimumSpanningTree/kruskal/Kruskal.java | 61 ++++++++++++++ .../minimumSpanningTree/kruskal/Node.java | 38 +++++++++ .../{prims => prim}/Node.java | 2 +- .../{prims => prim}/Prim.java | 7 +- .../{prims => prim}/README.md | 0 .../kruskal/KruskalTest.java | 84 +++++++++++++++++++ .../PrimsTest.java => prim/PrimTest.java} | 4 +- 10 files changed, 283 insertions(+), 10 deletions(-) create mode 100644 src/main/java/algorithms/minimumSpanningTree/kruskal/DisjointSet.java create mode 100644 src/main/java/algorithms/minimumSpanningTree/kruskal/Edge.java create mode 100644 src/main/java/algorithms/minimumSpanningTree/kruskal/Kruskal.java create mode 100644 src/main/java/algorithms/minimumSpanningTree/kruskal/Node.java rename src/main/java/algorithms/minimumSpanningTree/{prims => prim}/Node.java (96%) rename src/main/java/algorithms/minimumSpanningTree/{prims => prim}/Prim.java (93%) rename src/main/java/algorithms/minimumSpanningTree/{prims => prim}/README.md (100%) create mode 100644 src/test/java/algorithms/minimumSpanningTree/kruskal/KruskalTest.java rename src/test/java/algorithms/minimumSpanningTree/{prims/PrimsTest.java => prim/PrimTest.java} (96%) diff --git a/src/main/java/algorithms/minimumSpanningTree/README.md b/src/main/java/algorithms/minimumSpanningTree/README.md index e173d723..994f0d77 100644 --- a/src/main/java/algorithms/minimumSpanningTree/README.md +++ b/src/main/java/algorithms/minimumSpanningTree/README.md @@ -9,7 +9,7 @@ is a spanning tree with the minimum possible total edge weight. ## Prim's Algorithm We will discuss more implementation-specific details and complexity analysis in the respective folders. In short, -1. [Prim's Algorithm](prims) is a greedy algorithm that finds the minimum spanning tree of a graph by starting from an +1. [Prim's Algorithm](prim) is a greedy algorithm that finds the minimum spanning tree of a graph by starting from an arbitrary node (vertex) and adding the edge with the minimum weight that connects the current tree to a new node, adding the node to the current tree, until all nodes are included in the tree. diff --git a/src/main/java/algorithms/minimumSpanningTree/kruskal/DisjointSet.java b/src/main/java/algorithms/minimumSpanningTree/kruskal/DisjointSet.java new file mode 100644 index 00000000..7d5d7b01 --- /dev/null +++ b/src/main/java/algorithms/minimumSpanningTree/kruskal/DisjointSet.java @@ -0,0 +1,59 @@ +package algorithms.minimumSpanningTree.kruskal; + +import java.util.HashMap; +import java.util.Map; + +/** + * Implementation of quick-find structure; Turns a list of objects into a data structure that supports union operations + */ +public class DisjointSet { + private final Map identifier; + + /** + * Constructor to initialize Disjoint Set with a known list of listOfNodes. + * @param listOfNodes + */ + public DisjointSet(Node[] listOfNodes) { + identifier = new HashMap<>(); + for (Node currNode : listOfNodes) { + // Component identifier is the same as the node's identifier + identifier.put(currNode, currNode.getIdentifier()); + } + } + + /** + * Checks if object a and object b are in the same component. + * @param a + * @param b + * @return a boolean value + */ + public boolean find(Node a, Node b) { + if (!identifier.containsKey(a) || !identifier.containsKey(b)) { // key(s) does not even exist + return false; + } + return identifier.get(a).equals(identifier.get(b)); + } + + /** + * Merge the components of object a and object b. + * @param a + * @param b + */ + public void union(Node a, Node b) { + if (!identifier.containsKey(a) || !identifier.containsKey(b)) { // key(s) does not even exist; do nothing + return; + } + + if (identifier.get(a).equals(identifier.get(b))) { // already same; do nothing + return; + } + + String compOfA = identifier.get(a); + String compOfB = identifier.get(b); + for (Node obj : identifier.keySet()) { + if (identifier.get(obj).equals(compOfA)) { + identifier.put(obj, compOfB); + } + } + } +} diff --git a/src/main/java/algorithms/minimumSpanningTree/kruskal/Edge.java b/src/main/java/algorithms/minimumSpanningTree/kruskal/Edge.java new file mode 100644 index 00000000..3b27d238 --- /dev/null +++ b/src/main/java/algorithms/minimumSpanningTree/kruskal/Edge.java @@ -0,0 +1,36 @@ +package algorithms.minimumSpanningTree.kruskal; + +/** + * Edge class to represent an edge in the graph + */ +public class Edge implements Comparable { + private final Node source; + private final Node destination; + private final int weight; + + /** + * Constructor for Edge + */ + public Edge(Node source, Node destination, int weight) { + this.source = source; + this.destination = destination; + this.weight = weight; + } + + public int getWeight() { + return weight; + } + + public Node getSource() { + return source; + } + + public Node getDestination() { + return destination; + } + + @Override + public int compareTo(Edge other) { + return Integer.compare(this.weight, other.weight); + } +} diff --git a/src/main/java/algorithms/minimumSpanningTree/kruskal/Kruskal.java b/src/main/java/algorithms/minimumSpanningTree/kruskal/Kruskal.java new file mode 100644 index 00000000..0fc83125 --- /dev/null +++ b/src/main/java/algorithms/minimumSpanningTree/kruskal/Kruskal.java @@ -0,0 +1,61 @@ +package algorithms.minimumSpanningTree.kruskal; + +import java.util.ArrayList; +import java.util.List; + +/** + * Implementation of Prim's Algorithm to find MSTs + * Idea: + * Starting from any source (this will be the first node to be in the MST), pick the lightest outgoing edge, and + * include the node at the other end as part of a set of nodes S. Now repeatedly do the above by picking the lightest + * outgoing edge adjacent to any node in the MST (ensure the other end of the node is not already in the MST). + * Repeat until S contains all nodes in the graph. S is the MST. + * Actual implementation: + * No Edge class was implemented. Instead, the weights of the edges are stored in a 2D array adjacency matrix. An + * adjacency list may be used instead + * A Node class is implemented to encapsulate the current minimum weight to reach the node. + */ +public class Kruskal { + public static int[][] getKruskalMST(Node[] nodes, int[][] adjacencyMatrix) { + int numOfNodes = nodes.length; + List edges = new ArrayList<>(); + + // Convert adjacency matrix to list of edges + for (int i = 0; i < numOfNodes; i++) { + for (int j = i + 1; j < numOfNodes; j++) { + if (adjacencyMatrix[i][j] != Integer.MAX_VALUE) { + edges.add(new Edge(nodes[i], nodes[j], adjacencyMatrix[i][j])); + } + } + } + + // Sort edges by weight + edges.sort(Edge::compareTo); + + // Initialize Disjoint Set for vertex tracking + DisjointSet ds = new DisjointSet(nodes); + + int[][] mstMatrix = new int[numOfNodes][numOfNodes]; + + // Initialize the MST matrix to represent no edges with Integer.MAX_VALUE and 0 for self loops + for (int i = 0; i < nodes.length; i++) { + for (int j = 0; j < nodes.length; j++) { + mstMatrix[i][j] = (i == j) ? 0 : Integer.MAX_VALUE; + } + } + + // Process edges to build MST + for (Edge edge : edges) { + Node source = edge.getSource(); + Node destination = edge.getDestination(); + if (!ds.find(source, destination)) { + mstMatrix[source.getIndex()][destination.getIndex()] = edge.getWeight(); + mstMatrix[destination.getIndex()][source.getIndex()] = edge.getWeight(); + ds.union(source, destination); + } + } + + return mstMatrix; + } +} + diff --git a/src/main/java/algorithms/minimumSpanningTree/kruskal/Node.java b/src/main/java/algorithms/minimumSpanningTree/kruskal/Node.java new file mode 100644 index 00000000..ca6ae0e3 --- /dev/null +++ b/src/main/java/algorithms/minimumSpanningTree/kruskal/Node.java @@ -0,0 +1,38 @@ +package algorithms.minimumSpanningTree.kruskal; + +/** + * Node class to represent a node in the graph + * Note: In our Node class, we do not allow the currMinWeight to be updated after initialization to prevent any + * reference issues in the PriorityQueue. + */ +public class Node { + private final int index; // Index of this node in the adjacency matrix + private final String identifier; + + /** + * Constructor for Node + * @param identifier + * @param index + */ + public Node(String identifier, int index) { + this.identifier = identifier; + this.index = index; + } + + /** + * Getter for identifier + * @return identifier + */ + public String getIdentifier() { + return identifier; + } + + public int getIndex() { + return index; + } + + @Override + public String toString() { + return "Node{" + "identifier='" + identifier + '\'' + ", index=" + index + '}'; + } +} diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java b/src/main/java/algorithms/minimumSpanningTree/prim/Node.java similarity index 96% rename from src/main/java/algorithms/minimumSpanningTree/prims/Node.java rename to src/main/java/algorithms/minimumSpanningTree/prim/Node.java index fb465f00..c06a960d 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Node.java +++ b/src/main/java/algorithms/minimumSpanningTree/prim/Node.java @@ -1,4 +1,4 @@ -package algorithms.minimumSpanningTree.prims; +package algorithms.minimumSpanningTree.prim; /** * Node class to represent a node in the graph diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java b/src/main/java/algorithms/minimumSpanningTree/prim/Prim.java similarity index 93% rename from src/main/java/algorithms/minimumSpanningTree/prims/Prim.java rename to src/main/java/algorithms/minimumSpanningTree/prim/Prim.java index 9b59dce0..f53d382e 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prims/Prim.java +++ b/src/main/java/algorithms/minimumSpanningTree/prim/Prim.java @@ -1,4 +1,4 @@ -package algorithms.minimumSpanningTree.prims; +package algorithms.minimumSpanningTree.prim; import java.util.Arrays; import java.util.PriorityQueue; @@ -20,11 +20,6 @@ public static int[][] getPrimsMST(Node[] nodes, int[][] adjacencyMatrix) { PriorityQueue pq = new PriorityQueue<>((a, b) -> a.getCurrMinWeight() - b.getCurrMinWeight()); int[][] mstMatrix = new int[nodes.length][nodes.length]; // MST adjacency matrix - // Initialize mstMatrix with all edges set to Integer.MAX_VALUE - for (int[] row : mstMatrix) { - Arrays.fill(row, Integer.MAX_VALUE); - } - int[] parent = new int[nodes.length]; // To track the parent node of each node in the MST Arrays.fill(parent, -1); // Initialize parent array with -1, indicating no parent diff --git a/src/main/java/algorithms/minimumSpanningTree/prims/README.md b/src/main/java/algorithms/minimumSpanningTree/prim/README.md similarity index 100% rename from src/main/java/algorithms/minimumSpanningTree/prims/README.md rename to src/main/java/algorithms/minimumSpanningTree/prim/README.md diff --git a/src/test/java/algorithms/minimumSpanningTree/kruskal/KruskalTest.java b/src/test/java/algorithms/minimumSpanningTree/kruskal/KruskalTest.java new file mode 100644 index 00000000..76efc48c --- /dev/null +++ b/src/test/java/algorithms/minimumSpanningTree/kruskal/KruskalTest.java @@ -0,0 +1,84 @@ +package algorithms.minimumSpanningTree.kruskal; + +import static org.junit.Assert.assertArrayEquals; + +import org.junit.Test; + +public class KruskalTest { + @Test + public void test_simpleGraph() { + // Graph setup (Adjacency Matrix) + // B + // / \ + // 1 1 + // / \ + // A - 1 - C + int[][] adjacencyMatrix = { + {0, 1, 1}, // A: A-B, A-C + {1, 0, 1}, // B: B-A, B-C + {1, 1, 0} // C: C-A, C-B + }; + + Node[] nodes = { + new Node("A", 0), + new Node("B", 1), + new Node("C", 2) + }; + + // Run Kruskal's algorithm + int[][] actualMST = Kruskal.getKruskalMST(nodes, adjacencyMatrix); + + // Expected MST + // A -1- B -1- C + int[][] expectedMST = { + {0, 1, 1}, // A: A-B, A-C + {1, 0, Integer.MAX_VALUE}, // B: B-A + {1, Integer.MAX_VALUE, 0} // C: C-A + }; + + // Assertion + assertArrayEquals(expectedMST, actualMST); + } + + @Test + public void test_complexGraph() { + // Graph setup + // A + // / | \ + // 1 4 3 + /// | \ + //B --3-- D + // \ | / + // 2 4 1 + // \|/ + // C + int[][] adjacencyMatrix = { + {0, 1, 4, 3}, // A: A-B, A-C, A-D + {1, 0, 2, 3}, // B: B-A, B-C, B-D + {4, 2, 0, 1}, // C: C-A, C-B, C-D + {3, 3, 1, 0} // D: D-A, D-B, D-C + }; + + Node[] nodes = { + new Node("A", 0), + new Node("B", 1), + new Node("C", 2), + new Node("D", 3) + }; + + // Run Prim's algorithm + int[][] actualMST = Kruskal.getKruskalMST(nodes, adjacencyMatrix); + + // Expected MST + // Based on the graph, assuming the MST is correctly computed + int[][] expectedMST = { + {0, 1, Integer.MAX_VALUE, Integer.MAX_VALUE}, // A: A-B + {1, 0, 2, Integer.MAX_VALUE}, // B: B-A, B-C + {Integer.MAX_VALUE, 2, 0, 1}, // C: C-B, C-D + {Integer.MAX_VALUE, Integer.MAX_VALUE, 1, 0} // D: D-C + }; + + // Assertion + assertArrayEquals(expectedMST, actualMST); + } +} diff --git a/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java b/src/test/java/algorithms/minimumSpanningTree/prim/PrimTest.java similarity index 96% rename from src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java rename to src/test/java/algorithms/minimumSpanningTree/prim/PrimTest.java index f54ddbfa..6ecc531d 100644 --- a/src/test/java/algorithms/minimumSpanningTree/prims/PrimsTest.java +++ b/src/test/java/algorithms/minimumSpanningTree/prim/PrimTest.java @@ -1,10 +1,10 @@ -package algorithms.minimumSpanningTree.prims; +package algorithms.minimumSpanningTree.prim; import static org.junit.Assert.assertArrayEquals; import org.junit.Test; -public class PrimsTest { +public class PrimTest { @Test public void test_simpleGraph() { From 13925b37d7d5c15f31179a696f8c4d6d57de365d Mon Sep 17 00:00:00 2001 From: junnengsoo Date: Sun, 7 Apr 2024 00:06:36 +0800 Subject: [PATCH 49/51] Move helper classes to main class --- .../minimumSpanningTree/kruskal/Edge.java | 36 ---------- .../minimumSpanningTree/kruskal/Kruskal.java | 72 +++++++++++++++++++ .../minimumSpanningTree/kruskal/Node.java | 38 ---------- .../minimumSpanningTree/prim/Node.java | 59 --------------- .../minimumSpanningTree/prim/Prim.java | 59 +++++++++++++++ .../minimumSpanningTree/prim/PrimTest.java | 18 ++--- 6 files changed, 140 insertions(+), 142 deletions(-) delete mode 100644 src/main/java/algorithms/minimumSpanningTree/kruskal/Edge.java delete mode 100644 src/main/java/algorithms/minimumSpanningTree/kruskal/Node.java delete mode 100644 src/main/java/algorithms/minimumSpanningTree/prim/Node.java diff --git a/src/main/java/algorithms/minimumSpanningTree/kruskal/Edge.java b/src/main/java/algorithms/minimumSpanningTree/kruskal/Edge.java deleted file mode 100644 index 3b27d238..00000000 --- a/src/main/java/algorithms/minimumSpanningTree/kruskal/Edge.java +++ /dev/null @@ -1,36 +0,0 @@ -package algorithms.minimumSpanningTree.kruskal; - -/** - * Edge class to represent an edge in the graph - */ -public class Edge implements Comparable { - private final Node source; - private final Node destination; - private final int weight; - - /** - * Constructor for Edge - */ - public Edge(Node source, Node destination, int weight) { - this.source = source; - this.destination = destination; - this.weight = weight; - } - - public int getWeight() { - return weight; - } - - public Node getSource() { - return source; - } - - public Node getDestination() { - return destination; - } - - @Override - public int compareTo(Edge other) { - return Integer.compare(this.weight, other.weight); - } -} diff --git a/src/main/java/algorithms/minimumSpanningTree/kruskal/Kruskal.java b/src/main/java/algorithms/minimumSpanningTree/kruskal/Kruskal.java index 0fc83125..0bf55814 100644 --- a/src/main/java/algorithms/minimumSpanningTree/kruskal/Kruskal.java +++ b/src/main/java/algorithms/minimumSpanningTree/kruskal/Kruskal.java @@ -57,5 +57,77 @@ public static int[][] getKruskalMST(Node[] nodes, int[][] adjacencyMatrix) { return mstMatrix; } + + /** + * Node class to represent a node in the graph + * Note: In our Node class, we do not allow the currMinWeight to be updated after initialization to prevent any + * reference issues in the PriorityQueue. + */ + static class Node { + private final int index; // Index of this node in the adjacency matrix + private final String identifier; + + /** + * Constructor for Node + * @param identifier + * @param index + */ + public Node(String identifier, int index) { + this.identifier = identifier; + this.index = index; + } + + /** + * Getter for identifier + * @return identifier + */ + public String getIdentifier() { + return identifier; + } + + public int getIndex() { + return index; + } + + @Override + public String toString() { + return "Node{" + "identifier='" + identifier + '\'' + ", index=" + index + '}'; + } + } + + /** + * Edge class to represent an edge in the graph + */ + static class Edge implements Comparable { + private final Node source; + private final Node destination; + private final int weight; + + /** + * Constructor for Edge + */ + public Edge(Node source, Node destination, int weight) { + this.source = source; + this.destination = destination; + this.weight = weight; + } + + public int getWeight() { + return weight; + } + + public Node getSource() { + return source; + } + + public Node getDestination() { + return destination; + } + + @Override + public int compareTo(Edge other) { + return Integer.compare(this.weight, other.weight); + } + } } diff --git a/src/main/java/algorithms/minimumSpanningTree/kruskal/Node.java b/src/main/java/algorithms/minimumSpanningTree/kruskal/Node.java deleted file mode 100644 index ca6ae0e3..00000000 --- a/src/main/java/algorithms/minimumSpanningTree/kruskal/Node.java +++ /dev/null @@ -1,38 +0,0 @@ -package algorithms.minimumSpanningTree.kruskal; - -/** - * Node class to represent a node in the graph - * Note: In our Node class, we do not allow the currMinWeight to be updated after initialization to prevent any - * reference issues in the PriorityQueue. - */ -public class Node { - private final int index; // Index of this node in the adjacency matrix - private final String identifier; - - /** - * Constructor for Node - * @param identifier - * @param index - */ - public Node(String identifier, int index) { - this.identifier = identifier; - this.index = index; - } - - /** - * Getter for identifier - * @return identifier - */ - public String getIdentifier() { - return identifier; - } - - public int getIndex() { - return index; - } - - @Override - public String toString() { - return "Node{" + "identifier='" + identifier + '\'' + ", index=" + index + '}'; - } -} diff --git a/src/main/java/algorithms/minimumSpanningTree/prim/Node.java b/src/main/java/algorithms/minimumSpanningTree/prim/Node.java deleted file mode 100644 index c06a960d..00000000 --- a/src/main/java/algorithms/minimumSpanningTree/prim/Node.java +++ /dev/null @@ -1,59 +0,0 @@ -package algorithms.minimumSpanningTree.prim; - -/** - * Node class to represent a node in the graph - * Note: In our Node class, we do not allow the currMinWeight to be updated after initialization to prevent any - * reference issues in the PriorityQueue. - */ -public class Node { - private final int currMinWeight; // Current minimum weight to get to this node - private int index; // Index of this node in the adjacency matrix - private final String identifier; - - /** - * Constructor for Node - * @param identifier - * @param index - * @param currMinWeight - */ - public Node(String identifier, int index, int currMinWeight) { - this.identifier = identifier; - this.index = index; - this.currMinWeight = currMinWeight; - } - - /** - * Constructor for Node with default currMinWeight - * @param identifier - * @param index - */ - public Node(String identifier, int index) { - this.identifier = identifier; - this.index = index; - this.currMinWeight = Integer.MAX_VALUE; - } - - /** - * Getter and setter for currMinWeight - */ - public int getCurrMinWeight() { - return currMinWeight; - } - - /** - * Getter for identifier - * @return identifier - */ - public String getIdentifier() { - return identifier; - } - - public int getIndex() { - return index; - } - - @Override - public String toString() { - return "Node{" + "identifier='" + identifier + '\'' + ", index=" + index + '}'; - } -} diff --git a/src/main/java/algorithms/minimumSpanningTree/prim/Prim.java b/src/main/java/algorithms/minimumSpanningTree/prim/Prim.java index f53d382e..e5baad92 100644 --- a/src/main/java/algorithms/minimumSpanningTree/prim/Prim.java +++ b/src/main/java/algorithms/minimumSpanningTree/prim/Prim.java @@ -17,6 +17,7 @@ */ public class Prim { public static int[][] getPrimsMST(Node[] nodes, int[][] adjacencyMatrix) { + // Recall that PriorityQueue is a min heap by default PriorityQueue pq = new PriorityQueue<>((a, b) -> a.getCurrMinWeight() - b.getCurrMinWeight()); int[][] mstMatrix = new int[nodes.length][nodes.length]; // MST adjacency matrix @@ -72,5 +73,63 @@ public static int[][] getPrimsMST(Node[] nodes, int[][] adjacencyMatrix) { return mstMatrix; } + + /** + * Node class to represent a node in the graph + * Note: In our Node class, we do not allow the currMinWeight to be updated after initialization to prevent any + * reference issues in the PriorityQueue. + */ + static class Node { + private final int currMinWeight; // Current minimum weight to get to this node + private int index; // Index of this node in the adjacency matrix + private final String identifier; + + /** + * Constructor for Node + * @param identifier + * @param index + * @param currMinWeight + */ + public Node(String identifier, int index, int currMinWeight) { + this.identifier = identifier; + this.index = index; + this.currMinWeight = currMinWeight; + } + + /** + * Constructor for Node with default currMinWeight + * @param identifier + * @param index + */ + public Node(String identifier, int index) { + this.identifier = identifier; + this.index = index; + this.currMinWeight = Integer.MAX_VALUE; + } + + /** + * Getter and setter for currMinWeight + */ + public int getCurrMinWeight() { + return currMinWeight; + } + + /** + * Getter for identifier + * @return identifier + */ + public String getIdentifier() { + return identifier; + } + + public int getIndex() { + return index; + } + + @Override + public String toString() { + return "Node{" + "identifier='" + identifier + '\'' + ", index=" + index + '}'; + } + } } diff --git a/src/test/java/algorithms/minimumSpanningTree/prim/PrimTest.java b/src/test/java/algorithms/minimumSpanningTree/prim/PrimTest.java index 6ecc531d..bb0012d5 100644 --- a/src/test/java/algorithms/minimumSpanningTree/prim/PrimTest.java +++ b/src/test/java/algorithms/minimumSpanningTree/prim/PrimTest.java @@ -20,10 +20,10 @@ public void test_simpleGraph() { {1, 1, 0} // C: C-A, C-B }; - Node[] nodes = { - new Node("A", 0), - new Node("B", 1), - new Node("C", 2) + Prim.Node[] nodes = { + new Prim.Node("A", 0), + new Prim.Node("B", 1), + new Prim.Node("C", 2) }; // Run Prim's algorithm @@ -60,11 +60,11 @@ public void test_complexGraph() { {3, 3, 1, 0} // D: D-A, D-B, D-C }; - Node[] nodes = { - new Node("A", 0), - new Node("B", 1), - new Node("C", 2), - new Node("D", 3) + Prim.Node[] nodes = { + new Prim.Node("A", 0), + new Prim.Node("B", 1), + new Prim.Node("C", 2), + new Prim.Node("D", 3) }; // Run Prim's algorithm From a4a40976466d60763457ee63a28e673b84c066a5 Mon Sep 17 00:00:00 2001 From: junnengsoo Date: Sun, 7 Apr 2024 00:41:58 +0800 Subject: [PATCH 50/51] Use pre-existing DisjointSet class --- .../kruskal/DisjointSet.java | 59 ------------------- .../minimumSpanningTree/kruskal/Kruskal.java | 4 +- .../kruskal/KruskalTest.java | 18 +++--- 3 files changed, 12 insertions(+), 69 deletions(-) delete mode 100644 src/main/java/algorithms/minimumSpanningTree/kruskal/DisjointSet.java diff --git a/src/main/java/algorithms/minimumSpanningTree/kruskal/DisjointSet.java b/src/main/java/algorithms/minimumSpanningTree/kruskal/DisjointSet.java deleted file mode 100644 index 7d5d7b01..00000000 --- a/src/main/java/algorithms/minimumSpanningTree/kruskal/DisjointSet.java +++ /dev/null @@ -1,59 +0,0 @@ -package algorithms.minimumSpanningTree.kruskal; - -import java.util.HashMap; -import java.util.Map; - -/** - * Implementation of quick-find structure; Turns a list of objects into a data structure that supports union operations - */ -public class DisjointSet { - private final Map identifier; - - /** - * Constructor to initialize Disjoint Set with a known list of listOfNodes. - * @param listOfNodes - */ - public DisjointSet(Node[] listOfNodes) { - identifier = new HashMap<>(); - for (Node currNode : listOfNodes) { - // Component identifier is the same as the node's identifier - identifier.put(currNode, currNode.getIdentifier()); - } - } - - /** - * Checks if object a and object b are in the same component. - * @param a - * @param b - * @return a boolean value - */ - public boolean find(Node a, Node b) { - if (!identifier.containsKey(a) || !identifier.containsKey(b)) { // key(s) does not even exist - return false; - } - return identifier.get(a).equals(identifier.get(b)); - } - - /** - * Merge the components of object a and object b. - * @param a - * @param b - */ - public void union(Node a, Node b) { - if (!identifier.containsKey(a) || !identifier.containsKey(b)) { // key(s) does not even exist; do nothing - return; - } - - if (identifier.get(a).equals(identifier.get(b))) { // already same; do nothing - return; - } - - String compOfA = identifier.get(a); - String compOfB = identifier.get(b); - for (Node obj : identifier.keySet()) { - if (identifier.get(obj).equals(compOfA)) { - identifier.put(obj, compOfB); - } - } - } -} diff --git a/src/main/java/algorithms/minimumSpanningTree/kruskal/Kruskal.java b/src/main/java/algorithms/minimumSpanningTree/kruskal/Kruskal.java index 0bf55814..f3ec4290 100644 --- a/src/main/java/algorithms/minimumSpanningTree/kruskal/Kruskal.java +++ b/src/main/java/algorithms/minimumSpanningTree/kruskal/Kruskal.java @@ -3,6 +3,8 @@ import java.util.ArrayList; import java.util.List; +import dataStructures.disjointSet.weightedUnion.DisjointSet; + /** * Implementation of Prim's Algorithm to find MSTs * Idea: @@ -33,7 +35,7 @@ public static int[][] getKruskalMST(Node[] nodes, int[][] adjacencyMatrix) { edges.sort(Edge::compareTo); // Initialize Disjoint Set for vertex tracking - DisjointSet ds = new DisjointSet(nodes); + DisjointSet ds = new DisjointSet<>(nodes); int[][] mstMatrix = new int[numOfNodes][numOfNodes]; diff --git a/src/test/java/algorithms/minimumSpanningTree/kruskal/KruskalTest.java b/src/test/java/algorithms/minimumSpanningTree/kruskal/KruskalTest.java index 76efc48c..fdd18e32 100644 --- a/src/test/java/algorithms/minimumSpanningTree/kruskal/KruskalTest.java +++ b/src/test/java/algorithms/minimumSpanningTree/kruskal/KruskalTest.java @@ -19,10 +19,10 @@ public void test_simpleGraph() { {1, 1, 0} // C: C-A, C-B }; - Node[] nodes = { - new Node("A", 0), - new Node("B", 1), - new Node("C", 2) + Kruskal.Node[] nodes = { + new Kruskal.Node("A", 0), + new Kruskal.Node("B", 1), + new Kruskal.Node("C", 2) }; // Run Kruskal's algorithm @@ -59,11 +59,11 @@ public void test_complexGraph() { {3, 3, 1, 0} // D: D-A, D-B, D-C }; - Node[] nodes = { - new Node("A", 0), - new Node("B", 1), - new Node("C", 2), - new Node("D", 3) + Kruskal.Node[] nodes = { + new Kruskal.Node("A", 0), + new Kruskal.Node("B", 1), + new Kruskal.Node("C", 2), + new Kruskal.Node("D", 3) }; // Run Prim's algorithm From 47625d875848ecd2f308e83beffbbc6b773e9a9d Mon Sep 17 00:00:00 2001 From: junnengsoo Date: Mon, 8 Apr 2024 17:28:27 +0800 Subject: [PATCH 51/51] Complete Kruskal README --- .../algorithms/minimumSpanningTree/README.md | 13 +++++++++- .../minimumSpanningTree/kruskal/Kruskal.java | 15 +++++------ .../minimumSpanningTree/kruskal/README.md | 26 +++++++++++++++++++ 3 files changed, 45 insertions(+), 9 deletions(-) create mode 100644 src/main/java/algorithms/minimumSpanningTree/kruskal/README.md diff --git a/src/main/java/algorithms/minimumSpanningTree/README.md b/src/main/java/algorithms/minimumSpanningTree/README.md index 994f0d77..336ce58c 100644 --- a/src/main/java/algorithms/minimumSpanningTree/README.md +++ b/src/main/java/algorithms/minimumSpanningTree/README.md @@ -6,15 +6,26 @@ Minimum Spanning Tree (MST) algorithms are used to find the minimum spanning tre spanning tree of a graph is a connected, acyclic subgraph that includes all the vertices of the original graph. An MST is a spanning tree with the minimum possible total edge weight. -## Prim's Algorithm +## Prim's Algorithm and Kruskal's Algorithm We will discuss more implementation-specific details and complexity analysis in the respective folders. In short, 1. [Prim's Algorithm](prim) is a greedy algorithm that finds the minimum spanning tree of a graph by starting from an arbitrary node (vertex) and adding the edge with the minimum weight that connects the current tree to a new node, adding the node to the current tree, until all nodes are included in the tree. +2. [Kruskal's Algorithm](kruskal) is a greedy algorithm that finds the minimum spanning tree of a graph by sorting the +edges by weight and adding the edge with the minimum weight that does not form a cycle into the current tree. ## Notes +### Difference in use of Priority Queue in Prim's and Kruskal's Algorithm +Prim's Algorithm uses a priority queue to keep track of the minimum weight edge that connects the current tree to an +unexplored node, which could possibly be updated each time a node is popped from the queue. + +Kruskal's Algorithm uses a priority queue to sort all the edges by weight and the elements will not be updated at any +point in time. + +See the individual READMEs for more details. + ### Difference between Minimum Spanning Tree and Shortest Path It is important to note that a Minimum Spanning Tree of a graph does not represent the shortest path between all the nodes. See below for an example: diff --git a/src/main/java/algorithms/minimumSpanningTree/kruskal/Kruskal.java b/src/main/java/algorithms/minimumSpanningTree/kruskal/Kruskal.java index f3ec4290..23f2196e 100644 --- a/src/main/java/algorithms/minimumSpanningTree/kruskal/Kruskal.java +++ b/src/main/java/algorithms/minimumSpanningTree/kruskal/Kruskal.java @@ -6,16 +6,14 @@ import dataStructures.disjointSet.weightedUnion.DisjointSet; /** - * Implementation of Prim's Algorithm to find MSTs + * Implementation of Kruskal's Algorithm to find MSTs * Idea: - * Starting from any source (this will be the first node to be in the MST), pick the lightest outgoing edge, and - * include the node at the other end as part of a set of nodes S. Now repeatedly do the above by picking the lightest - * outgoing edge adjacent to any node in the MST (ensure the other end of the node is not already in the MST). - * Repeat until S contains all nodes in the graph. S is the MST. + * Sort all edges by weight in non-decreasing order. Consider the edges in this order. If an edge does not form a cycle + * with the edges already in the MST, add it to the MST. Repeat until all nodes are in the MST. * Actual implementation: - * No Edge class was implemented. Instead, the weights of the edges are stored in a 2D array adjacency matrix. An - * adjacency list may be used instead - * A Node class is implemented to encapsulate the current minimum weight to reach the node. + * An Edge class is implemented for easier sorting of edges by weight and for identifying the source and destination. + * A Node class is implemented for easier tracking of nodes in the graph for the disjoint set. + * A DisjointSet class is used to track the nodes in the graph and to determine if adding an edge will form a cycle. */ public class Kruskal { public static int[][] getKruskalMST(Node[] nodes, int[][] adjacencyMatrix) { @@ -37,6 +35,7 @@ public static int[][] getKruskalMST(Node[] nodes, int[][] adjacencyMatrix) { // Initialize Disjoint Set for vertex tracking DisjointSet ds = new DisjointSet<>(nodes); + // MST adjacency matrix to be returned int[][] mstMatrix = new int[numOfNodes][numOfNodes]; // Initialize the MST matrix to represent no edges with Integer.MAX_VALUE and 0 for self loops diff --git a/src/main/java/algorithms/minimumSpanningTree/kruskal/README.md b/src/main/java/algorithms/minimumSpanningTree/kruskal/README.md new file mode 100644 index 00000000..579745d7 --- /dev/null +++ b/src/main/java/algorithms/minimumSpanningTree/kruskal/README.md @@ -0,0 +1,26 @@ +# Kruskal's Algorithm + +## Background +Kruskal's Algorithm is a greedy algorithm used to find the minimum spanning tree (MST) of a connected, weighted graph. +It works by sorting all the edges in the graph by their weight in non-decreasing order and then adding the smallest edge +to the MST, provided it does not form a cycle with the already included edges. This is repeated until all vertices are +included in the MST. + +## Implementation Details +Similar to Prim's Algorithm, Kruskal's Algorithm uses a priority queue (binary heap). However, instead of comparing +the minimum edge weight to each vertex, all the weights of the individual edges are compared instead. Note that we do +not need any decrease key operations as all edges are considered independently and will not be updated at any point in +time. + +A [disjoint set](/dataStructures/disjointSet/weightedUnion) data structure is used to keep track of the connectivity of +vertices and detect cycles. + +## Complexity Analysis + +**Time Complexity:** +Sorting the edges by weight: O(E log E) = O(E log V), where V and E is the number of vertices and edges respectively. +Union-Find operations: O(E α(V)), where α is the inverse Ackermann function. +Overall complexity: O(E log V) + +**Space Complexity:** +O(V + E) for the storage of vertices in the disjoint set and edges in the priority queue. \ No newline at end of file