From e7a85c1648a9f01862bfa4910fec275a45c87039 Mon Sep 17 00:00:00 2001 From: Sridhar Gopinath Date: Mon, 15 May 2017 14:38:34 +0530 Subject: [PATCH 01/88] URL changes Corrected few URLs. --- README.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index c7660169..411022f8 100644 --- a/README.md +++ b/README.md @@ -158,30 +158,30 @@ This is a collection of algorithms and data structures which I've implement over + [Interpolation [sorted array input only]](src/com/jwetherell/algorithms/Sequences/InterpolationSearch.java) ## Sequences -* [Find longest common subsequence (dynamic programming)](src/com/jwetherell/algorithms/Sequences/LongestCommonSubsequence.java) -* [Find longest increasing subsequence (dynamic programming)](src/com/jwetherell/algorithms/Sequences/LongestIncreasingSubsequence.java) -* [Find number of times a subsequence occurs in a sequence (dynamic programming)](src/com/jwetherell/algorithms/Sequences/SubsequenceCounter.java) -* [Find i-th element in a Fibonacci sequence](src/com/jwetherell/algorithms/Sequences/FibonacciSequence.java) +* [Find longest common subsequence (dynamic programming)](src/com/jwetherell/algorithms/sequence/LongestCommonSubsequence.java) +* [Find longest increasing subsequence (dynamic programming)](src/com/jwetherell/algorithms/sequence/LongestIncreasingSubsequence.java) +* [Find number of times a subsequence occurs in a sequence (dynamic programming)](src/com/jwetherell/algorithms/sequence/SubsequenceCounter.java) +* [Find i-th element in a Fibonacci sequence](src/com/jwetherell/algorithms/sequence/FibonacciSequence.java) + using a loop + using recursion + using matrix multiplication + using Binet's formula -* [Find total of all elements in a sequence(Arithmetic Progression)](src/com/jwetherell/algorithms/Sequences/ArithmeticProgression.java) +* [Find total of all elements in a sequence(Arithmetic Progression)](src/com/jwetherell/algorithms/sequence/ArithmeticProgression.java) + using a loop + using Triangular numbers -* [Largest sum of contiguous subarray (Kadane's algorithm)](src/com/jwetherell/algorithms/Sequences/LargestSumContiguousSubarray.java) -* [Longest palin­dromic sub­se­quence (dynamic programming)](src/com/jwetherell/algorithms/Sequences/LongestPalin­dromicSub­se­quence.java) +* [Largest sum of contiguous subarray (Kadane's algorithm)](src/com/jwetherell/algorithms/sequence/LargestSumContiguousSubarray.java) +* [Longest palin­dromic sub­se­quence (dynamic programming)](src/com/jwetherell/algorithms/sequence/LongestPalindromicSubsequence.java) ## Sorts -* [American Flag Sort](src/com/jwetherell/algorithms/Sorts/AmericanFlagSort.java) -* [Bubble Sort](src/com/jwetherell/algorithms/Sorts/BubbleSort.java) -* [Counting Sort (Integers only)](src/com/jwetherell/algorithms/Sorts/CountingSort.java) -* [Heap Sort](src/com/jwetherell/algorithms/Sorts/HeapSort.java) -* [Insertion Sort](src/com/jwetherell/algorithms/Sorts/InsertionSort.java) -* [Merge Sort](src/com/jwetherell/algorithms/Sorts/AMergeSort.java) -* [Quick Sort](src/com/jwetherell/algorithms/Sorts/QuickSort.java) -* [Radix Sort (Integers only)](src/com/jwetherell/algorithms/Sorts/RadixSort.java) -* [Shell's Sort](src/com/jwetherell/algorithms/Sorts/ShellSort.java) +* [American Flag Sort](src/com/jwetherell/algorithms/sorts/AmericanFlagSort.java) +* [Bubble Sort](src/com/jwetherell/algorithms/sorts/BubbleSort.java) +* [Counting Sort (Integers only)](src/com/jwetherell/algorithms/sorts/CountingSort.java) +* [Heap Sort](src/com/jwetherell/algorithms/sorts/HeapSort.java) +* [Insertion Sort](src/com/jwetherell/algorithms/sorts/InsertionSort.java) +* [Merge Sort](src/com/jwetherell/algorithms/sorts/MergeSort.java) +* [Quick Sort](src/com/jwetherell/algorithms/sorts/QuickSort.java) +* [Radix Sort (Integers only)](src/com/jwetherell/algorithms/sorts/RadixSort.java) +* [Shell's Sort](src/com/jwetherell/algorithms/sorts/ShellSort.java) ## String Functions ### [String Functions](src/com/jwetherell/algorithms/strings/StringFunctions.java) From c18be2d9d59f7ed87e0f33481a676de873c96c14 Mon Sep 17 00:00:00 2001 From: Dmytro Kytsmen Date: Wed, 17 May 2017 16:35:43 +0300 Subject: [PATCH 02/88] Fixed bug in ProbingHashMap - clear() method was not clearing array elements in loop, missing square braces --- src/com/jwetherell/algorithms/data_structures/HashMap.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/jwetherell/algorithms/data_structures/HashMap.java b/src/com/jwetherell/algorithms/data_structures/HashMap.java index cf7775df..9e39ceeb 100644 --- a/src/com/jwetherell/algorithms/data_structures/HashMap.java +++ b/src/com/jwetherell/algorithms/data_structures/HashMap.java @@ -514,7 +514,7 @@ public V remove(K key) { @Override public void clear() { for (int i=0; i Date: Thu, 18 May 2017 13:38:46 +0300 Subject: [PATCH 03/88] Fixed bug in ProbingHashMap - indexOf method could cause indexOutOfBoundariesException if the hashcode of a key was less than zero --- src/com/jwetherell/algorithms/data_structures/HashMap.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/com/jwetherell/algorithms/data_structures/HashMap.java b/src/com/jwetherell/algorithms/data_structures/HashMap.java index cf7775df..f4ad1c0f 100644 --- a/src/com/jwetherell/algorithms/data_structures/HashMap.java +++ b/src/com/jwetherell/algorithms/data_structures/HashMap.java @@ -597,9 +597,9 @@ private int getNextIndex(int input) { * @return Integer which represents the key. */ private int indexOf(K key) { - int k = key.hashCode() % hashingKey; - if (k>=array.length) - k = k - ((k/array.length) * array.length); + int k = Math.abs(key.hashCode()) % hashingKey; + if (k >= array.length) + k = k - ((k / array.length) * array.length); return k; } From c4f9e679281f82fef8540c1d1a3f56072078d2f6 Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Thu, 18 May 2017 12:29:33 -0400 Subject: [PATCH 04/88] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 411022f8..336efd49 100644 --- a/README.md +++ b/README.md @@ -44,9 +44,9 @@ This is a collection of algorithms and data structures which I've implement over * [Hash Array Mapped Trie (HAMT)](src/com/jwetherell/algorithms/data_structures/HashArrayMappedTrie.java) * [Hash Map (associative array)](src/com/jwetherell/algorithms/data_structures/HashMap.java) * [Interval Tree](src/com/jwetherell/algorithms/data_structures/IntervalTree.java) -* [Implicit Key Treap]((src/com/jwetherell/algorithms/data_structures/ImplicitKeyTreap.java)) +* [Implicit Key Treap](src/com/jwetherell/algorithms/data_structures/ImplicitKeyTreap.java) * [KD Tree (k-dimensional tree or k-d tree)](src/com/jwetherell/algorithms/data_structures/KDTree.java) -* [List [backed by an array or a linked list]]((src/com/jwetherell/algorithms/data_structures/List.java)) +* [List [backed by an array or a linked list]](src/com/jwetherell/algorithms/data_structures/List.java) * [Matrix](src/com/jwetherell/algorithms/data_structures/Matrix.java) * [Patricia Trie](src/com/jwetherell/algorithms/data_structures/PatriciaTrie.java) * [Quad-Tree (Point-Region or MX-CIF)](src/com/jwetherell/algorithms/data_structures/QuadTree.java) From 2b6c2030fec5aa4499cb6ae93339a504c2dadfa1 Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Thu, 18 May 2017 12:30:43 -0400 Subject: [PATCH 05/88] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 336efd49..96ba019b 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ This is a collection of algorithms and data structures which I've implement over * [Patricia Trie](src/com/jwetherell/algorithms/data_structures/PatriciaTrie.java) * [Quad-Tree (Point-Region or MX-CIF)](src/com/jwetherell/algorithms/data_structures/QuadTree.java) * [Queue [backed by an array or a linked list]](src/com/jwetherell/algorithms/data_structures/Queue.java) -* [Radix Trie (associative array) [backed by a Patricia Trie]](src/com/jwetherell/algorithms/data_structures/RadixTree.java) +* [Radix Trie (associative array) [backed by a Patricia Trie]](src/com/jwetherell/algorithms/data_structures/RadixTrie.java) * [Red-Black Tree](src/com/jwetherell/algorithms/data_structures/RedBlackTree.java) * [Segment Tree](src/com/jwetherell/algorithms/data_structures/SegmentTree.java) * [Skip List](src/com/jwetherell/algorithms/data_structures/SkipList.java) From f97f78d3455102e5a48bf872a7a46ebfb8447a47 Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Thu, 18 May 2017 12:31:44 -0400 Subject: [PATCH 06/88] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 96ba019b..353318c5 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ This is a collection of algorithms and data structures which I've implement over * [Splay Tree](src/com/jwetherell/algorithms/data_structures/SplayTree.java) * [Stack [backed by an array or a linked list]](src/com/jwetherell/algorithms/data_structures/Stack.java) * [Suffix Tree (Ukkonen's algorithm)](src/com/jwetherell/algorithms/data_structures/SuffixTree.java) -* [Suffix Trie [backed by a Trie]](src/com/jwetherell/algorithms/data_structures/SufficTrie.java) +* [Suffix Trie [backed by a Trie]](src/com/jwetherell/algorithms/data_structures/SuffixTrie.java) * [Treap](src/com/jwetherell/algorithms/data_structures/Treap.java) * [Tree Map (associative array) [backed by an AVL Tree]](src/com/jwetherell/algorithms/data_structures/TreeMap.java) * [Trie](src/com/jwetherell/algorithms/data_structures/Trie.java) From fce3b3339ced052981820e99050b89f714369f1d Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Thu, 18 May 2017 12:34:58 -0400 Subject: [PATCH 07/88] Update README.md --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 353318c5..563f5ea5 100644 --- a/README.md +++ b/README.md @@ -149,13 +149,13 @@ This is a collection of algorithms and data structures which I've implement over ## Search * Get index of value in array - + [Linear](src/com/jwetherell/algorithms/Sequences/LinearSearch.java) - + [Quickselect](src/com/jwetherell/algorithms/Sequences/QuickSelect.java) - + [Binary [sorted array input only]](src/com/jwetherell/algorithms/Sequences/BinarySearch.java) - + [Lower bound [sorted array input only]](src/com/jwetherell/algorithms/Sequences/LpperBound.java) - + [Upper bound [sorted array input only]](src/com/jwetherell/algorithms/Sequences/UpperBound.java) + + [Linear](src/com/jwetherell/algorithms/search/LinearSearch.java) + + [Quickselect](src/com/jwetherell/algorithms/search/QuickSelect.java) + + [Binary [sorted array input only]](src/com/jwetherell/algorithms/search/BinarySearch.java) + + [Lower bound [sorted array input only]](src/com/jwetherell/algorithms/search/LpperBound.java) + + [Upper bound [sorted array input only]](src/com/jwetherell/algorithms/search/UpperBound.java) + Optimized binary (binary until a threashold then linear) [sorted array input only] - + [Interpolation [sorted array input only]](src/com/jwetherell/algorithms/Sequences/InterpolationSearch.java) + + [Interpolation [sorted array input only]](src/com/jwetherell/algorithms/search/InterpolationSearch.java) ## Sequences * [Find longest common subsequence (dynamic programming)](src/com/jwetherell/algorithms/sequence/LongestCommonSubsequence.java) From b3ff518853ea133e65de3e2944512799cdd8c06d Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Thu, 18 May 2017 12:35:47 -0400 Subject: [PATCH 08/88] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 563f5ea5..e44fe929 100644 --- a/README.md +++ b/README.md @@ -152,7 +152,7 @@ This is a collection of algorithms and data structures which I've implement over + [Linear](src/com/jwetherell/algorithms/search/LinearSearch.java) + [Quickselect](src/com/jwetherell/algorithms/search/QuickSelect.java) + [Binary [sorted array input only]](src/com/jwetherell/algorithms/search/BinarySearch.java) - + [Lower bound [sorted array input only]](src/com/jwetherell/algorithms/search/LpperBound.java) + + [Lower bound [sorted array input only]](src/com/jwetherell/algorithms/search/LowerBound.java) + [Upper bound [sorted array input only]](src/com/jwetherell/algorithms/search/UpperBound.java) + Optimized binary (binary until a threashold then linear) [sorted array input only] + [Interpolation [sorted array input only]](src/com/jwetherell/algorithms/search/InterpolationSearch.java) From 21e0046a19e4cc7e73f3bc77c44745eba2c975b7 Mon Sep 17 00:00:00 2001 From: Piotr Kruk Date: Tue, 6 Jun 2017 12:46:17 +0200 Subject: [PATCH 09/88] Added Manacher's algorithm --- .../algorithms/strings/Manacher.java | 74 +++++++++++++++++++ .../strings/test/ManacherTests.java | 39 ++++++++++ 2 files changed, 113 insertions(+) create mode 100644 src/com/jwetherell/algorithms/strings/Manacher.java create mode 100644 test/com/jwetherell/algorithms/strings/test/ManacherTests.java diff --git a/src/com/jwetherell/algorithms/strings/Manacher.java b/src/com/jwetherell/algorithms/strings/Manacher.java new file mode 100644 index 00000000..7a067ac4 --- /dev/null +++ b/src/com/jwetherell/algorithms/strings/Manacher.java @@ -0,0 +1,74 @@ +package com.jwetherell.algorithms.strings; + +/** + * The longest palindromic substring or longest symmetric factor problem + * is the problem of finding a maximum-length contiguous substring of a given string that is also a palindrome. + * + * The longest palindromic substring problem should not be confused with + * the different problem of finding the longest palindromic subsequence. + * + * Manacher's algorithm finds the longest palindromic substring in linear time O(n); where n = length(input) + * https://en.wikipedia.org/wiki/Longest_palindromic_substring#Manacher.27s_algorithm + * @author Piotr Kruk + */ +public class Manacher { + private Manacher() {} + + /** + * This function implements Manacher's algorithm that finds + * the longest palindromic substring in a linear time + * If there is no unique longest palindromic substring it returns the first one to occur + * @param input + * @return the longest palindromic substring in input + */ + public static String getLongestPalindromicSubstring(String input) { + if (input == null) + return null; + + int length = input.length(); + if (length == 0) + return ""; + + // arr represents input string in a way that will act the same for strings of even and uneven length + // i.e. '#' is placed between each letter from input + final char[] arr = new char[2 * length + 1]; + for (int i = length - 1; i >= 0; i--) { + arr[2 * i + 1] = input.charAt(i); + arr[2 * i] = '#'; + } + arr[2 * length] = '#'; + + int arrLength = length * 2; + + // LPS[i] - palindrome span(radius) with center at arr[i] + int[] LPS = new int[arrLength + 1]; + int p = 0; + for (int i = 1; i <= arrLength; i++) { + LPS[i] = 0; + if (LPS[p] + p >= i) + LPS[i] = Math.min(LPS[2 * p - i], p + LPS[p] - i); + while (i + LPS[i] + 1 <= arrLength && i - LPS[i] - 1 >= 0 && arr[i + LPS[i] + 1] == arr[i - LPS[i] - 1]) + LPS[i]++; + if (p + LPS[p] < i + LPS[i]) + p = i; + } + + // find the palindrome with the biggest span + int valueMax = 0; + int indexMax = 0; + for (int i = 0; i < arrLength; i++) { + if (valueMax < LPS[i]) { + valueMax = LPS[i]; + indexMax = i; + } + } + + // reconstruct the palindrome given its index in LPS and span + int palindromeSpan = valueMax / 2; + if (indexMax % 2 == 0) { + return input.substring(indexMax/2 - palindromeSpan, indexMax/2 + palindromeSpan); + } else { + return input.substring(indexMax/2 - palindromeSpan, indexMax/2 + palindromeSpan + 1); + } + } +} diff --git a/test/com/jwetherell/algorithms/strings/test/ManacherTests.java b/test/com/jwetherell/algorithms/strings/test/ManacherTests.java new file mode 100644 index 00000000..276575ff --- /dev/null +++ b/test/com/jwetherell/algorithms/strings/test/ManacherTests.java @@ -0,0 +1,39 @@ +package com.jwetherell.algorithms.strings.test; + +import static org.junit.Assert.assertEquals; +import java.util.List; +import java.util.Arrays; +import com.jwetherell.algorithms.strings.Manacher; +import org.junit.Test; + +public class ManacherTests { + + @Test + public void testGetLongestPalindromicSubstring() throws Exception { + final List data = Arrays.asList( + new Object[][]{ + {null, null}, + {"", ""}, + {"a", "a"}, + {"aa", "aa"}, + {"aaa", "aaa"}, + {"abaa", "aba"}, + {"abba", "abba"}, + {"abbaaa", "abba"}, + {"abbabb", "bbabb"}, + {"bananas", "anana"}, + {"bakskskba", "ksksk"}, + {"itisneveroddoreven", "neveroddoreven"}, + {"ABCDEFGHIJKLMNOPQRSTUVWXYZ", "A"}, + {"I like bananas", "anana"} + + } + ); + for (Object[] testCase: data) { + String input = (String) testCase[0]; + String expected = (String) testCase[1]; + String result = Manacher.getLongestPalindromicSubstring(input); + assertEquals(expected, result); + } + } +} From 19498e1a104709d3f084947ecd287da8f7a90ae3 Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Wed, 7 Jun 2017 17:50:26 -0400 Subject: [PATCH 10/88] Code cleanup for merge request --- .../algorithms/graph/DepthFirstTraversal.java | 16 +++++++++++----- .../jwetherell/algorithms/strings/Manacher.java | 17 +++++++++++------ 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/com/jwetherell/algorithms/graph/DepthFirstTraversal.java b/src/com/jwetherell/algorithms/graph/DepthFirstTraversal.java index b2f970e8..8d216a6b 100644 --- a/src/com/jwetherell/algorithms/graph/DepthFirstTraversal.java +++ b/src/com/jwetherell/algorithms/graph/DepthFirstTraversal.java @@ -1,16 +1,23 @@ +package com.jwetherell.algorithms.graph; + import java.util.Stack; -//implemented Depth First Travesal in given "Directed graph" (Adjacany matrix) +/** + * Implemented Depth First Traversal in given the "Directed graph" (Adjacency matrix) + * + * @author Justin Wetherell + * + */ class DepthFirstTraversal { public static int[] arr; public static int k = 0; public static void depthFirstTraversal(int[][] a, int[] visited,int source){ - for (int i = 0; i < visited.length; i++) { + for (int i = 0; i < visited.length; i++) visited[i] = -1; - } - Stackstack = new Stack(); + + final Stack stack = new Stack(); int element = source; int i = source; int n = visited.length - 1; @@ -38,4 +45,3 @@ public static void depthFirstTraversal(int[][] a, int[] visited,int source){ } } } - diff --git a/src/com/jwetherell/algorithms/strings/Manacher.java b/src/com/jwetherell/algorithms/strings/Manacher.java index 7a067ac4..af715875 100644 --- a/src/com/jwetherell/algorithms/strings/Manacher.java +++ b/src/com/jwetherell/algorithms/strings/Manacher.java @@ -3,21 +3,26 @@ /** * The longest palindromic substring or longest symmetric factor problem * is the problem of finding a maximum-length contiguous substring of a given string that is also a palindrome. - * + *

* The longest palindromic substring problem should not be confused with * the different problem of finding the longest palindromic subsequence. - * + *
* Manacher's algorithm finds the longest palindromic substring in linear time O(n); where n = length(input) + *
* https://en.wikipedia.org/wiki/Longest_palindromic_substring#Manacher.27s_algorithm + *
* @author Piotr Kruk + * @author Justin Wetherell */ public class Manacher { + private Manacher() {} /** * This function implements Manacher's algorithm that finds * the longest palindromic substring in a linear time * If there is no unique longest palindromic substring it returns the first one to occur + * * @param input * @return the longest palindromic substring in input */ @@ -25,7 +30,7 @@ public static String getLongestPalindromicSubstring(String input) { if (input == null) return null; - int length = input.length(); + final int length = input.length(); if (length == 0) return ""; @@ -38,10 +43,10 @@ public static String getLongestPalindromicSubstring(String input) { } arr[2 * length] = '#'; - int arrLength = length * 2; + final int arrLength = length * 2; // LPS[i] - palindrome span(radius) with center at arr[i] - int[] LPS = new int[arrLength + 1]; + final int[] LPS = new int[arrLength + 1]; int p = 0; for (int i = 1; i <= arrLength; i++) { LPS[i] = 0; @@ -64,7 +69,7 @@ public static String getLongestPalindromicSubstring(String input) { } // reconstruct the palindrome given its index in LPS and span - int palindromeSpan = valueMax / 2; + final int palindromeSpan = valueMax / 2; if (indexMax % 2 == 0) { return input.substring(indexMax/2 - palindromeSpan, indexMax/2 + palindromeSpan); } else { From b9d56399ea9527888f98f7a3217e31bf34551825 Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Wed, 7 Jun 2017 18:02:33 -0400 Subject: [PATCH 11/88] Update README.md --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e44fe929..1286fbad 100644 --- a/README.md +++ b/README.md @@ -198,9 +198,10 @@ This is a collection of algorithms and data structures which I've implement over + using additional storage (a StringBuilder) + using in-place symetric element compares * Subsets of characters in a String -* Edit (Levenshtein) Distance of two Strings +* Edit (Levenshtein) Distance of two Strings (Recursive, Iterative) +* [Manacher's algorithm] (src/com/jwetherell/algorithms/strings/Manacher.java) * [KMP (Knuth–Morris–Pratt) Algorithm - Length of maximal prefix-suffix for each prefix](src/com/jwetherell/algorithms/strings/KnuthMorrisPratt.java) * [String rotations](src/com/jwetherell/algorithms/strings/Rotation.java) - + Findin lexicographically minimal string rotation - + Findin lexicographically maximal string rotation + + Find in lexicographically minimal string rotation + + Find in lexicographically maximal string rotation From df4289cb5a8e73e57fc561f71784270f0f4adf88 Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Wed, 7 Jun 2017 18:03:38 -0400 Subject: [PATCH 12/88] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1286fbad..b24bb978 100644 --- a/README.md +++ b/README.md @@ -199,9 +199,9 @@ This is a collection of algorithms and data structures which I've implement over + using in-place symetric element compares * Subsets of characters in a String * Edit (Levenshtein) Distance of two Strings (Recursive, Iterative) -* [Manacher's algorithm] (src/com/jwetherell/algorithms/strings/Manacher.java) -* [KMP (Knuth–Morris–Pratt) Algorithm - Length of maximal prefix-suffix for each prefix](src/com/jwetherell/algorithms/strings/KnuthMorrisPratt.java) -* [String rotations](src/com/jwetherell/algorithms/strings/Rotation.java) +### [Manacher's algorithm](src/com/jwetherell/algorithms/strings/Manacher.java) +### [KMP (Knuth–Morris–Pratt) Algorithm - Length of maximal prefix-suffix for each prefix](src/com/jwetherell/algorithms/strings/KnuthMorrisPratt.java) +### [String rotations](src/com/jwetherell/algorithms/strings/Rotation.java) + Find in lexicographically minimal string rotation + Find in lexicographically maximal string rotation From 5a7121341f86ebd6b310048966736ea0247133ab Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Wed, 7 Jun 2017 18:04:45 -0400 Subject: [PATCH 13/88] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b24bb978..f09c17c1 100644 --- a/README.md +++ b/README.md @@ -199,7 +199,7 @@ This is a collection of algorithms and data structures which I've implement over + using in-place symetric element compares * Subsets of characters in a String * Edit (Levenshtein) Distance of two Strings (Recursive, Iterative) -### [Manacher's algorithm](src/com/jwetherell/algorithms/strings/Manacher.java) +### [Manacher's algorithm (Finding the Palindrome)](src/com/jwetherell/algorithms/strings/Manacher.java) ### [KMP (Knuth–Morris–Pratt) Algorithm - Length of maximal prefix-suffix for each prefix](src/com/jwetherell/algorithms/strings/KnuthMorrisPratt.java) ### [String rotations](src/com/jwetherell/algorithms/strings/Rotation.java) + Find in lexicographically minimal string rotation From a9228306322110f11aec5e323278bc41ec5c14ab Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Wed, 7 Jun 2017 19:21:09 -0400 Subject: [PATCH 14/88] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f09c17c1..d724f3ec 100644 --- a/README.md +++ b/README.md @@ -199,7 +199,7 @@ This is a collection of algorithms and data structures which I've implement over + using in-place symetric element compares * Subsets of characters in a String * Edit (Levenshtein) Distance of two Strings (Recursive, Iterative) -### [Manacher's algorithm (Finding the Palindrome)](src/com/jwetherell/algorithms/strings/Manacher.java) +### [Manacher's algorithm (Find the longest Palindrome)](src/com/jwetherell/algorithms/strings/Manacher.java) ### [KMP (Knuth–Morris–Pratt) Algorithm - Length of maximal prefix-suffix for each prefix](src/com/jwetherell/algorithms/strings/KnuthMorrisPratt.java) ### [String rotations](src/com/jwetherell/algorithms/strings/Rotation.java) + Find in lexicographically minimal string rotation From ffe59040f626ae14063c2cdaf23c366ea57f5a9f Mon Sep 17 00:00:00 2001 From: arytmetyk Date: Wed, 21 Jun 2017 21:26:51 +0200 Subject: [PATCH 15/88] Added exponentiation algorithms. --- README.md | 4 ++ .../mathematics/Exponentiation.java | 57 +++++++++++++++++++ .../mathematics/test/ExponentiationTest.java | 46 +++++++++++++++ .../timing/ExponentiationTiming.java | 27 +++++++++ 4 files changed, 134 insertions(+) create mode 100644 src/com/jwetherell/algorithms/mathematics/Exponentiation.java create mode 100644 test/com/jwetherell/algorithms/mathematics/test/ExponentiationTest.java create mode 100644 test/com/jwetherell/algorithms/mathematics/timing/ExponentiationTiming.java diff --git a/README.md b/README.md index d724f3ec..9ff6c2d3 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,10 @@ This is a collection of algorithms and data structures which I've implement over + using only shifts + using logarithms + [Fast Fourier Transform](src/com/jwetherell/algorithms/mathematics/FastFourierTransform.java) +* [Exponentiation](src/com/jwetherell/algorithms/mathematics/Exponentiation.java) + + recursive exponentiation + + fast recursive exponentiation + + fast modular recursive exponentiation * [Primes](src/com/jwetherell/algorithms/mathematics/Primes.java) + is prime + prime factorization diff --git a/src/com/jwetherell/algorithms/mathematics/Exponentiation.java b/src/com/jwetherell/algorithms/mathematics/Exponentiation.java new file mode 100644 index 00000000..e6c1c156 --- /dev/null +++ b/src/com/jwetherell/algorithms/mathematics/Exponentiation.java @@ -0,0 +1,57 @@ +package com.jwetherell.algorithms.mathematics; + +/** + * Recursive function of exponentiation is just an implementation of definition. + * https://en.wikipedia.org/wiki/Exponentiation + * Complexity - O(N) where N is exponent. + *

+ * Fast exponentiation's complexity is O(lg N) + * https://en.wikipedia.org/wiki/Exponentiation_by_squaring + *

+ * Modular exponentiation is similar. + * https://en.wikipedia.org/wiki/Modular_exponentiation + * Here is implemented fast version of this algorithm so a complexity is also O(lg N) + *
+ * + * @author Bartlomiej Drozd + */ + + +public class Exponentiation { + + public static int recursiveExponentiation(int base, int exponent) { + if (exponent == 0) return 1; + if (exponent == 1) return base; + + return recursiveExponentiation(base, exponent - 1) * base; + + } + + public static int fastRecursiveExponentiation(int base, int exponent) { + if (exponent == 0) return 1; + if (exponent == 1) return base; + + int resultOnHalfExponent = fastRecursiveExponentiation(base, exponent / 2); + + if ((exponent % 2) == 0) + return resultOnHalfExponent * resultOnHalfExponent; + else + return resultOnHalfExponent * resultOnHalfExponent * base; + + } + + public static int fastRecursiveExponentiationModulo(int base, int exponent, int mod) { + if (exponent == 0) return 1; + if (exponent == 1) return base; + + int resultOnHalfExponent = fastRecursiveExponentiation(base, exponent / 2); + + if ((exponent % 2) == 0) + return (resultOnHalfExponent * resultOnHalfExponent) % mod; + else + return (((resultOnHalfExponent * resultOnHalfExponent) % mod) * base) % mod; + + } + + +} diff --git a/test/com/jwetherell/algorithms/mathematics/test/ExponentiationTest.java b/test/com/jwetherell/algorithms/mathematics/test/ExponentiationTest.java new file mode 100644 index 00000000..d8129d66 --- /dev/null +++ b/test/com/jwetherell/algorithms/mathematics/test/ExponentiationTest.java @@ -0,0 +1,46 @@ +package com.jwetherell.algorithms.mathematics.test; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; + +import com.jwetherell.algorithms.mathematics.Exponentiation; + + +import static org.junit.Assert.assertEquals; + + +public class ExponentiationTest { + + @Test + public void recusriveExponentiationTest() { + List baseList = Arrays.asList(1, 2, 4, 6, 8, 17, 24); + List exponentList = Arrays.asList(1000, 27, 14, 11, 10, 7, 5); + List expectedResultList = Arrays.asList(1, 134217728, 268435456, 362797056, 1073741824, 410338673, 7962624); + + for (int i = 0; i < expectedResultList.size(); i++) + assertEquals(expectedResultList.get(i), Exponentiation.recursiveExponentiation(baseList.get(i), exponentList.get(i))); + } + + @Test + public void fastRecusriveExponentiationTest() { + List baseList = Arrays.asList(1, 2, 4, 6, 8, 17, 24); + List exponentList = Arrays.asList(1000, 27, 14, 11, 10, 7, 5); + List expectedResultList = Arrays.asList(1, 134217728, 268435456, 362797056, 1073741824, 410338673, 7962624); + + for (int i = 0; i < expectedResultList.size(); i++) + assertEquals(expectedResultList.get(i), Exponentiation.fastRecursiveExponentiation(baseList.get(i), exponentList.get(i))); + } + + @Test + public void fastRecusriveExponentiationModuloTest() { + List baseList = Arrays.asList(1, 2, 4, 6, 8, 17, 24); + List exponentList = Arrays.asList(1000, 27, 14, 11, 10, 7, 5); + List divisorList = Arrays.asList(2, 6, 3, 2, 9, 11, 5); + List expectedResultList = Arrays.asList(1, 2, 1, 0, 1, 8, 4); + + for (int i = 0; i < expectedResultList.size(); i++) + assertEquals(expectedResultList.get(i), Exponentiation.fastRecursiveExponentiationModulo(baseList.get(i), exponentList.get(i), divisorList.get(i))); + } +} diff --git a/test/com/jwetherell/algorithms/mathematics/timing/ExponentiationTiming.java b/test/com/jwetherell/algorithms/mathematics/timing/ExponentiationTiming.java new file mode 100644 index 00000000..b4ca9f3f --- /dev/null +++ b/test/com/jwetherell/algorithms/mathematics/timing/ExponentiationTiming.java @@ -0,0 +1,27 @@ +package com.jwetherell.algorithms.mathematics.timing; + +/** + * Notice that 2^1000 is out of integer range so returned result is not correct. + * It is a reason why exponentiation modulo is useful. + * But it does not matter when you want to compare speed of these two algorithms. + */ + +import com.jwetherell.algorithms.mathematics.Exponentiation; + + +public class ExponentiationTiming { + public static void main(String[] args) { + System.out.println("Calculating a power using a recursive function."); + long before = System.nanoTime(); + Exponentiation.recursiveExponentiation(2, 1000); + long after = System.nanoTime(); + System.out.println("Computed in " + (after - before) + " ns"); + + System.out.println("Calculating a power using a fast recursive function."); + before = System.nanoTime(); + Exponentiation.fastRecursiveExponentiation(2, 1000); + after = System.nanoTime(); + System.out.println("Computed in " + (after - before) + " ns"); + + } +} From 8d1ec17791ecaa8dcb6ec8982de82cecd9cd57c9 Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Wed, 21 Jun 2017 15:42:48 -0400 Subject: [PATCH 16/88] Code clean-up for pull request --- .../jwetherell/algorithms/graph/AStar.java | 1 + .../mathematics/Exponentiation.java | 41 ++++++++++--------- .../test/ImplicitKeyTreapTests.java | 1 + .../algorithms/graph/test/Graphs.java | 1 + .../mathematics/test/ExponentiationTest.java | 1 - .../timing/ExponentiationTiming.java | 7 +--- 6 files changed, 27 insertions(+), 25 deletions(-) diff --git a/src/com/jwetherell/algorithms/graph/AStar.java b/src/com/jwetherell/algorithms/graph/AStar.java index 4fd267db..3a957dbc 100644 --- a/src/com/jwetherell/algorithms/graph/AStar.java +++ b/src/com/jwetherell/algorithms/graph/AStar.java @@ -115,6 +115,7 @@ protected int distanceBetween(Graph.Vertex start, Graph.Vertex next) { /** * Default heuristic: cost to each vertex is 1. */ + @SuppressWarnings("unused") protected int heuristicCostEstimate(Graph.Vertex start, Graph.Vertex goal) { return 1; } diff --git a/src/com/jwetherell/algorithms/mathematics/Exponentiation.java b/src/com/jwetherell/algorithms/mathematics/Exponentiation.java index e6c1c156..e432318c 100644 --- a/src/com/jwetherell/algorithms/mathematics/Exponentiation.java +++ b/src/com/jwetherell/algorithms/mathematics/Exponentiation.java @@ -2,37 +2,42 @@ /** * Recursive function of exponentiation is just an implementation of definition. + *

* https://en.wikipedia.org/wiki/Exponentiation + *

* Complexity - O(N) where N is exponent. *

* Fast exponentiation's complexity is O(lg N) - * https://en.wikipedia.org/wiki/Exponentiation_by_squaring *

+ * https://en.wikipedia.org/wiki/Exponentiation_by_squaring + *
* Modular exponentiation is similar. + *

* https://en.wikipedia.org/wiki/Modular_exponentiation - * Here is implemented fast version of this algorithm so a complexity is also O(lg N) + *

+ * This implementation is the fast version of this algorithm with a complexity of O(lg N) also *
- * * @author Bartlomiej Drozd + * @author Justin Wetherell */ - - public class Exponentiation { public static int recursiveExponentiation(int base, int exponent) { - if (exponent == 0) return 1; - if (exponent == 1) return base; + if (exponent == 0) + return 1; + if (exponent == 1) + return base; return recursiveExponentiation(base, exponent - 1) * base; - } public static int fastRecursiveExponentiation(int base, int exponent) { - if (exponent == 0) return 1; - if (exponent == 1) return base; - - int resultOnHalfExponent = fastRecursiveExponentiation(base, exponent / 2); + if (exponent == 0) + return 1; + if (exponent == 1) + return base; + final int resultOnHalfExponent = fastRecursiveExponentiation(base, exponent / 2); if ((exponent % 2) == 0) return resultOnHalfExponent * resultOnHalfExponent; else @@ -41,17 +46,15 @@ public static int fastRecursiveExponentiation(int base, int exponent) { } public static int fastRecursiveExponentiationModulo(int base, int exponent, int mod) { - if (exponent == 0) return 1; - if (exponent == 1) return base; - - int resultOnHalfExponent = fastRecursiveExponentiation(base, exponent / 2); + if (exponent == 0) + return 1; + if (exponent == 1) + return base; + final int resultOnHalfExponent = fastRecursiveExponentiation(base, exponent / 2); if ((exponent % 2) == 0) return (resultOnHalfExponent * resultOnHalfExponent) % mod; else return (((resultOnHalfExponent * resultOnHalfExponent) % mod) * base) % mod; - } - - } diff --git a/test/com/jwetherell/algorithms/data_structures/test/ImplicitKeyTreapTests.java b/test/com/jwetherell/algorithms/data_structures/test/ImplicitKeyTreapTests.java index 27a1ea9a..2ec109cd 100644 --- a/test/com/jwetherell/algorithms/data_structures/test/ImplicitKeyTreapTests.java +++ b/test/com/jwetherell/algorithms/data_structures/test/ImplicitKeyTreapTests.java @@ -202,6 +202,7 @@ private static > void moveToBack(MyTreap t, int begin t.setRoot(n); } + @SuppressWarnings("unused") private static String toString(Class type, Object[] array) { final StringBuilder builder = new StringBuilder(); for (Object a : array) diff --git a/test/com/jwetherell/algorithms/graph/test/Graphs.java b/test/com/jwetherell/algorithms/graph/test/Graphs.java index bd770c89..e63e5602 100644 --- a/test/com/jwetherell/algorithms/graph/test/Graphs.java +++ b/test/com/jwetherell/algorithms/graph/test/Graphs.java @@ -984,6 +984,7 @@ public void testAStarDirected() { * Makes a zero weighted directed graph, so that there is an edge between two vertices if the difference between the * vertices values is >= K */ + @SuppressWarnings("unused") private static final Graph makeDirectedGraph(int N, int K, int[] values) { final List> vertices = new ArrayList>(values.length); for (int i=0; i Date: Wed, 21 Jun 2017 16:11:27 -0400 Subject: [PATCH 17/88] Fixed a couple of 'possible' bugs --- src/com/jwetherell/algorithms/data_structures/Matrix.java | 4 ++-- src/com/jwetherell/algorithms/data_structures/SkipList.java | 2 +- src/com/jwetherell/algorithms/data_structures/SplayTree.java | 2 +- src/com/jwetherell/algorithms/mathematics/Multiplication.java | 2 +- src/com/jwetherell/algorithms/numbers/Integers.java | 2 +- src/com/jwetherell/algorithms/strings/StringFunctions.java | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/com/jwetherell/algorithms/data_structures/Matrix.java b/src/com/jwetherell/algorithms/data_structures/Matrix.java index 8f919cbf..717b757c 100644 --- a/src/com/jwetherell/algorithms/data_structures/Matrix.java +++ b/src/com/jwetherell/algorithms/data_structures/Matrix.java @@ -251,7 +251,7 @@ public Matrix multiply(Matrix input) { T m2 = column[i]; BigDecimal result2 = ((BigDecimal)m1).multiply(((BigDecimal)m2)); - result.add(result2); + result = result.add(result2); } output.set(r, c, (T)result); } else if (test instanceof BigInteger) { @@ -261,7 +261,7 @@ public Matrix multiply(Matrix input) { T m2 = column[i]; BigInteger result2 = ((BigInteger)m1).multiply(((BigInteger)m2)); - result.add(result2); + result = result.add(result2); } output.set(r, c, (T)result); } else if (test instanceof Long) { diff --git a/src/com/jwetherell/algorithms/data_structures/SkipList.java b/src/com/jwetherell/algorithms/data_structures/SkipList.java index 4396d54e..5743fa32 100644 --- a/src/com/jwetherell/algorithms/data_structures/SkipList.java +++ b/src/com/jwetherell/algorithms/data_structures/SkipList.java @@ -373,9 +373,9 @@ protected Node getNext(int idx) { public String toString() { StringBuilder builder = new StringBuilder(); builder.append("data=").append(data); - int size = next.length; if (next!=null) { builder.append("\n").append("next=["); + int size = next.length; for (int i=0; i n = next[i]; if (n!=null) builder.append(n.data); diff --git a/src/com/jwetherell/algorithms/data_structures/SplayTree.java b/src/com/jwetherell/algorithms/data_structures/SplayTree.java index 1540b99a..90ed9c27 100644 --- a/src/com/jwetherell/algorithms/data_structures/SplayTree.java +++ b/src/com/jwetherell/algorithms/data_structures/SplayTree.java @@ -67,7 +67,7 @@ public boolean contains(T value) { private void splay(Node node) { Node parent = node.parent; Node grandParent = (parent != null) ? parent.parent : null; - if (parent == root) { + if (parent != null && parent == root) { grandParent = parent.parent; // Zig step root = node; diff --git a/src/com/jwetherell/algorithms/mathematics/Multiplication.java b/src/com/jwetherell/algorithms/mathematics/Multiplication.java index c26687b3..98db58a7 100644 --- a/src/com/jwetherell/algorithms/mathematics/Multiplication.java +++ b/src/com/jwetherell/algorithms/mathematics/Multiplication.java @@ -183,7 +183,7 @@ public static String multiplyUsingLoopWithStringInput(String a, String b) { sb.append('-'); boolean zeroCheck = true; for (Integer s : res) { - if (zeroCheck && s.equals("0")) + if (zeroCheck && s.equals(0)) continue; zeroCheck = false; sb.append(s); diff --git a/src/com/jwetherell/algorithms/numbers/Integers.java b/src/com/jwetherell/algorithms/numbers/Integers.java index c36dcc82..809ac8a6 100644 --- a/src/com/jwetherell/algorithms/numbers/Integers.java +++ b/src/com/jwetherell/algorithms/numbers/Integers.java @@ -87,7 +87,7 @@ public static final boolean powerOfTwoUsingLog(int numberToCheck) { int number = numberToCheck; double doubleLog = Math.log10(number) / Math.log10(2); int intLog = (int) doubleLog; - if (doubleLog == intLog) + if (Double.compare(doubleLog, intLog) == 0) return true; return false; } diff --git a/src/com/jwetherell/algorithms/strings/StringFunctions.java b/src/com/jwetherell/algorithms/strings/StringFunctions.java index ceca5062..a4e05234 100644 --- a/src/com/jwetherell/algorithms/strings/StringFunctions.java +++ b/src/com/jwetherell/algorithms/strings/StringFunctions.java @@ -197,7 +197,7 @@ public static final boolean isPalindromeWithAdditionalStorage(String string) { public static final boolean isPalindromeInPlace(String string) { final char[] array = string.toCharArray(); final int length = array.length - 1; - final int half = Math.round(array.length / 2); + final int half = Math.round(array.length / 2f); char a, b; for (int i = length; i >= half; i--) { a = array[length - i]; From 1da66fcf377afdf0916ceed0267977ff15b3bfca Mon Sep 17 00:00:00 2001 From: arytmetyk Date: Wed, 21 Jun 2017 22:59:57 +0200 Subject: [PATCH 18/88] Fixed modulo exponentiation issue. --- .../algorithms/mathematics/Exponentiation.java | 15 ++++++++------- .../mathematics/test/ExponentiationTest.java | 8 ++++---- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/com/jwetherell/algorithms/mathematics/Exponentiation.java b/src/com/jwetherell/algorithms/mathematics/Exponentiation.java index e432318c..0b29b967 100644 --- a/src/com/jwetherell/algorithms/mathematics/Exponentiation.java +++ b/src/com/jwetherell/algorithms/mathematics/Exponentiation.java @@ -17,24 +17,25 @@ *

* This implementation is the fast version of this algorithm with a complexity of O(lg N) also *
+ * * @author Bartlomiej Drozd * @author Justin Wetherell */ public class Exponentiation { public static int recursiveExponentiation(int base, int exponent) { - if (exponent == 0) + if (exponent == 0) return 1; - if (exponent == 1) + if (exponent == 1) return base; return recursiveExponentiation(base, exponent - 1) * base; } public static int fastRecursiveExponentiation(int base, int exponent) { - if (exponent == 0) + if (exponent == 0) return 1; - if (exponent == 1) + if (exponent == 1) return base; final int resultOnHalfExponent = fastRecursiveExponentiation(base, exponent / 2); @@ -46,12 +47,12 @@ public static int fastRecursiveExponentiation(int base, int exponent) { } public static int fastRecursiveExponentiationModulo(int base, int exponent, int mod) { - if (exponent == 0) + if (exponent == 0) return 1; - if (exponent == 1) + if (exponent == 1) return base; - final int resultOnHalfExponent = fastRecursiveExponentiation(base, exponent / 2); + final int resultOnHalfExponent = fastRecursiveExponentiationModulo(base, exponent / 2, mod); if ((exponent % 2) == 0) return (resultOnHalfExponent * resultOnHalfExponent) % mod; else diff --git a/test/com/jwetherell/algorithms/mathematics/test/ExponentiationTest.java b/test/com/jwetherell/algorithms/mathematics/test/ExponentiationTest.java index 5b50d842..6f84cf57 100644 --- a/test/com/jwetherell/algorithms/mathematics/test/ExponentiationTest.java +++ b/test/com/jwetherell/algorithms/mathematics/test/ExponentiationTest.java @@ -34,10 +34,10 @@ public void fastRecusriveExponentiationTest() { @Test public void fastRecusriveExponentiationModuloTest() { - List baseList = Arrays.asList(1, 2, 4, 6, 8, 17, 24); - List exponentList = Arrays.asList(1000, 27, 14, 11, 10, 7, 5); - List divisorList = Arrays.asList(2, 6, 3, 2, 9, 11, 5); - List expectedResultList = Arrays.asList(1, 2, 1, 0, 1, 8, 4); + List baseList = Arrays.asList(1, 2, 4, 6, 8, 17, 24, 2); + List exponentList = Arrays.asList(1000, 27, 14, 11, 10, 7, 5, 1089); + List divisorList = Arrays.asList(2, 6, 3, 2, 9, 11, 5, 2179); + List expectedResultList = Arrays.asList(1, 2, 1, 0, 1, 8, 4, 2178); for (int i = 0; i < expectedResultList.size(); i++) assertEquals(expectedResultList.get(i), Exponentiation.fastRecursiveExponentiationModulo(baseList.get(i), exponentList.get(i), divisorList.get(i))); From d88feae453ce20c7989eda6d2539d28dc6ec6e44 Mon Sep 17 00:00:00 2001 From: arytmetyk Date: Thu, 22 Jun 2017 00:32:57 +0200 Subject: [PATCH 19/88] Added Miller-Rabin primality test algorithm. --- README.md | 1 + .../algorithms/mathematics/Primes.java | 86 +++++++++++--- .../mathematics/test/Mathematics.java | 106 ++++++++++-------- 3 files changed, 132 insertions(+), 61 deletions(-) diff --git a/README.md b/README.md index 9ff6c2d3..eeb6fb6c 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,7 @@ This is a collection of algorithms and data structures which I've implement over + is prime + prime factorization + sieve of eratosthenes + + Miller-Rabin test + [Co-Primes (relatively prime, mutually prime)](src/com/jwetherell/algorithms/mathematics/Coprimes.java) + [Greatest Common Divisor](src/com/jwetherell/algorithms/mathematics/GreatestCommonDivisor.java) - using Euclid's algorithm diff --git a/src/com/jwetherell/algorithms/mathematics/Primes.java b/src/com/jwetherell/algorithms/mathematics/Primes.java index b0a9d912..8597c1dc 100644 --- a/src/com/jwetherell/algorithms/mathematics/Primes.java +++ b/src/com/jwetherell/algorithms/mathematics/Primes.java @@ -2,8 +2,36 @@ import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; + +/** + * isPrime() using the square root properties + *

+ * 1 is not a prime. All primes except 2 are odd. All primes greater than 3 + * can be written in the form 6k+/-1. Any number n can have only one + * primefactor greater than n . The consequence for primality testing of a + * number n is: if we cannot find a number f less than or equal n that + * divides n then n is prime: the only primefactor of n is n itself + *
+ * Sieve of Eratosthenes is an another way to check if number is prime. + *

+ * https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes + *
+ * Miller-Rabin primality test is the fastest way to check if number is prime. + * Regular version of this algorithm returns false when number is composite and true + * when number is probably prime. Here is implemented a deterministic version of this + * algorithm, witnesses are not randomized. Used set of witnesses guarantees that result + * will be correct for sure (not probably) for any number lower than 10^18. + *

+ * https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test + *
+ * + * @author Justin Wetherell + * @author Bartlomiej Drozd + */ + public class Primes { public static final Map getPrimeFactorization(long number) { @@ -34,15 +62,6 @@ public static final Map getPrimeFactorization(long number) { return map; } - /* - * isPrime() using the square root properties - * - * 1 is not a prime. All primes except 2 are odd. All primes greater than 3 - * can be written in the form 6k+/-1. Any number n can have only one - * primefactor greater than n . The consequence for primality testing of a - * number n is: if we cannot find a number f less than or equal n that - * divides n then n is prime: the only primefactor of n is n itself - */ public static final boolean isPrime(long number) { if (number == 1) return false; @@ -52,11 +71,11 @@ public static final boolean isPrime(long number) { return false; // short circuit if (number < 9) return true; // we have already excluded 4, 6 and 8. - // (testing for 5 & 7) + // (testing for 5 & 7) if (number % 3 == 0) return false; // short circuit long r = (long) (Math.sqrt(number)); // n rounded to the greatest integer - // r so that r*r<=n + // r so that r*r<=n int f = 5; while (f <= r) { if (number % f == 0) @@ -80,14 +99,14 @@ public static final boolean sieveOfEratosthenes(int number) { if (sieve == null || number >= sieve.length) { int start = 2; if (sieve == null) { - sieve = new boolean[number+1]; + sieve = new boolean[number + 1]; } else if (number >= sieve.length) { - sieve = Arrays.copyOf(sieve, number+1); + sieve = Arrays.copyOf(sieve, number + 1); } for (int i = start; i <= Math.sqrt(number); i++) { if (!sieve[i]) { - for (int j = i*2; j <= number; j += i) { + for (int j = i * 2; j <= number; j += i) { sieve[j] = true; } } @@ -95,4 +114,43 @@ public static final boolean sieveOfEratosthenes(int number) { } return !sieve[number]; } + + + public static final boolean millerRabinTest(int number) { + List witnesses = Arrays.asList(2, 325, 9375, 28178, 450775, 9780504, 1795265022); + + if (number == 0 || number == 1) + return false; + if (number == 2 || number == 3) + return true; + + int maximumPowerOf2 = 0; + while (((number - 1) % Exponentiation.fastRecursiveExponentiation(2, maximumPowerOf2)) == 0) + maximumPowerOf2++; + maximumPowerOf2--; + + int d = (number - 1) / Exponentiation.fastRecursiveExponentiation(2, maximumPowerOf2); + + boolean isPrime = true; + + for (int a : witnesses) { + if (a > number) break; + if (Exponentiation.fastRecursiveExponentiationModulo(a, d, number) != 1) { + boolean isLocalPrime = false; + for (int r = 0; r < maximumPowerOf2; r++) { + if (Exponentiation.fastRecursiveExponentiationModulo(a, d * Exponentiation.fastRecursiveExponentiation(2, r), number) == (number - 1)) { + isLocalPrime = true; + break; + } + } + if (!isLocalPrime) { + isPrime = false; + break; + } + } + } + + + return isPrime; + } } diff --git a/test/com/jwetherell/algorithms/mathematics/test/Mathematics.java b/test/com/jwetherell/algorithms/mathematics/test/Mathematics.java index 39bb8026..5d5fa1ee 100644 --- a/test/com/jwetherell/algorithms/mathematics/test/Mathematics.java +++ b/test/com/jwetherell/algorithms/mathematics/test/Mathematics.java @@ -3,9 +3,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import java.util.HashMap; -import java.util.Map; -import java.util.Random; +import java.util.*; import org.junit.Test; @@ -21,6 +19,7 @@ public class Mathematics { private static final int MAX = 1000; private static final Random RANDOM = new Random(); + private static int nextRandomInt(int min, int max) { // nextInt is normally exclusive of the top value, // so add 1 to make it inclusive @@ -36,28 +35,28 @@ public void multiplication() { long result = Multiplication.multiplyUsingLoop(a, b); long check = Multiplication.multiplication(a, b); assertTrue("Multiplication using a loop. a=" + a + " b=" + b + " result=" + result + " check=" + check, (result == check)); - + result = Multiplication.multiplyUsingRecursion(a, b); check = Multiplication.multiplication(a, b); assertTrue("Multiplication using recursion. a=" + a + " b=" + b + " result=" + result + " check=" + check, (result == check)); - + result = Multiplication.multiplyUsingShift(a, b); check = Multiplication.multiplication(a, b); assertTrue("Multiplication using shifts. a=" + a + " b=" + b + " result=" + result + " check=" + check, (result == check)); - + result = Multiplication.multiplyUsingLogs(a, b); check = Multiplication.multiplication(a, b); assertTrue("Multiplication using logs. a=" + a + " b=" + b + " result=" + result + " check=" + check, (result == check)); - + result = Integer.parseInt(Multiplication.multiplyUsingFFT(Integer.toString(a), Integer.toString(b))); check = Multiplication.multiplication(a, b); assertTrue("Multiplication using FFT. a=" + a + " b=" + b + " result=" + result + " check=" + check, (result == check)); - + result = Integer.parseInt(Multiplication.multiplyUsingLoopWithStringInput(Integer.toString(a), Integer.toString(b))); check = Multiplication.multiplication(a, b); assertTrue("Multiplication using loop with string input. a=" + a + " b=" + b + " result=" + result + " check=" + check, (result == check)); - - result = Multiplication.multiplyUsingLoopWithIntegerInput(a,b); + + result = Multiplication.multiplyUsingLoopWithIntegerInput(a, b); check = Multiplication.multiplication(a, b); assertTrue("Multiplication using loop with int input. a=" + a + " b=" + b + " result=" + result + " check=" + check, (result == check)); } @@ -67,28 +66,28 @@ public void multiplication() { long result = Multiplication.multiplyUsingLoop(a, b); long check = Multiplication.multiplication(a, b); assertTrue("Multiplication using a loop. a=" + a + " b=" + b + " result=" + result + " check=" + check, (result == check)); - + result = Multiplication.multiplyUsingRecursion(a, b); check = Multiplication.multiplication(a, b); assertTrue("Multiplication using recursion. a=" + a + " b=" + b + " result=" + result + " check=" + check, (result == check)); - + result = Multiplication.multiplyUsingShift(a, b); check = Multiplication.multiplication(a, b); assertTrue("Multiplication using shifts. a=" + a + " b=" + b + " result=" + result + " check=" + check, (result == check)); - + result = Multiplication.multiplyUsingLogs(a, b); check = Multiplication.multiplication(a, b); assertTrue("Multiplication using logs. a=" + a + " b=" + b + " result=" + result + " check=" + check, (result == check)); - + result = Integer.parseInt(Multiplication.multiplyUsingFFT(Integer.toString(a), Integer.toString(b))); check = Multiplication.multiplication(a, b); assertTrue("Multiplication using FFT. a=" + a + " b=" + b + " result=" + result + " check=" + check, (result == check)); - + result = Integer.parseInt(Multiplication.multiplyUsingLoopWithStringInput(Integer.toString(a), Integer.toString(b))); check = Multiplication.multiplication(a, b); assertTrue("Multiplication using loop with string input. a=" + a + " b=" + b + " result=" + result + " check=" + check, (result == check)); - - result = Multiplication.multiplyUsingLoopWithIntegerInput(a,b); + + result = Multiplication.multiplyUsingLoopWithIntegerInput(a, b); check = Multiplication.multiplication(a, b); assertTrue("Multiplication using loop with int input. a=" + a + " b=" + b + " result=" + result + " check=" + check, (result == check)); } @@ -99,59 +98,59 @@ public void multiplication() { long result = Multiplication.multiplyUsingLoop(a, b); long check = Multiplication.multiplication(a, b); assertTrue("Multiplication using a loop. a=" + a + " b=" + b + " result=" + result + " check=" + check, (result == check)); - + result = Multiplication.multiplyUsingRecursion(a, b); check = Multiplication.multiplication(a, b); assertTrue("Multiplication using recursion. a=" + a + " b=" + b + " result=" + result + " check=" + check, (result == check)); - + result = Multiplication.multiplyUsingShift(a, b); check = Multiplication.multiplication(a, b); assertTrue("Multiplication using shifts. a=" + a + " b=" + b + " result=" + result + " check=" + check, (result == check)); - + result = Multiplication.multiplyUsingLogs(a, b); check = Multiplication.multiplication(a, b); assertTrue("Multiplication using logs. a=" + a + " b=" + b + " result=" + result + " check=" + check, (result == check)); - + result = Integer.parseInt(Multiplication.multiplyUsingFFT(Integer.toString(a), Integer.toString(b))); check = Multiplication.multiplication(a, b); assertTrue("Multiplication using FFT. a=" + a + " b=" + b + " result=" + result + " check=" + check, (result == check)); - + result = Integer.parseInt(Multiplication.multiplyUsingLoopWithStringInput(Integer.toString(a), Integer.toString(b))); check = Multiplication.multiplication(a, b); assertTrue("Multiplication using loop with string input. a=" + a + " b=" + b + " result=" + result + " check=" + check, (result == check)); - - result = Multiplication.multiplyUsingLoopWithIntegerInput(a,b); + + result = Multiplication.multiplyUsingLoopWithIntegerInput(a, b); check = Multiplication.multiplication(a, b); assertTrue("Multiplication using loop with int input. a=" + a + " b=" + b + " result=" + result + " check=" + check, (result == check)); } // negative * negative - a *= -1; + a *= -1; { long result = Multiplication.multiplyUsingLoop(a, b); long check = Multiplication.multiplication(a, b); assertTrue("Multiplication using a loop. a=" + a + " b=" + b + " result=" + result + " check=" + check, (result == check)); - + result = Multiplication.multiplyUsingRecursion(a, b); check = Multiplication.multiplication(a, b); assertTrue("Multiplication using recursion. a=" + a + " b=" + b + " result=" + result + " check=" + check, (result == check)); - + result = Multiplication.multiplyUsingShift(a, b); check = Multiplication.multiplication(a, b); assertTrue("Multiplication using shifts. a=" + a + " b=" + b + " result=" + result + " check=" + check, (result == check)); - + result = Multiplication.multiplyUsingLogs(a, b); check = Multiplication.multiplication(a, b); assertTrue("Multiplication using logs. a=" + a + " b=" + b + " result=" + result + " check=" + check, (result == check)); - + result = Integer.parseInt(Multiplication.multiplyUsingFFT(Integer.toString(a), Integer.toString(b))); check = Multiplication.multiplication(a, b); assertTrue("Multiplication using FFT. a=" + a + " b=" + b + " result=" + result + " check=" + check, (result == check)); - + result = Integer.parseInt(Multiplication.multiplyUsingLoopWithStringInput(Integer.toString(a), Integer.toString(b))); check = Multiplication.multiplication(a, b); assertTrue("Multiplication using loop with string input. a=" + a + " b=" + b + " result=" + result + " check=" + check, (result == check)); - - result = Multiplication.multiplyUsingLoopWithIntegerInput(a,b); + + result = Multiplication.multiplyUsingLoopWithIntegerInput(a, b); check = Multiplication.multiplication(a, b); assertTrue("Multiplication using loop with int input. a=" + a + " b=" + b + " result=" + result + " check=" + check, (result == check)); } @@ -184,25 +183,25 @@ public void division() { @Test public void knapsack() { - int[] values = { 7, 4, 8, 6, 2, 5 }; - int[] weights = { 2, 3, 5, 4, 2, 3 }; + int[] values = {7, 4, 8, 6, 2, 5}; + int[] weights = {2, 3, 5, 4, 2, 3}; int capacity = 9; int[] result = Knapsack.zeroOneKnapsack(values, weights, capacity); - int[] check = new int[]{5,3,0}; - for (int i=0; i primeNumbers = Arrays.asList(2, 3, 7, 23, 2179, 25657, 34123); + List compositeNumbers = Arrays.asList(4, 9, 27, 2457, 26575, 34121); + + for (int prime : primeNumbers) + assertTrue("Miller-Rabin test error. " + prime, Primes.millerRabinTest(prime)); + + for (int composite : compositeNumbers) + assertFalse("Miller-Rabin test error. " + composite, Primes.millerRabinTest(composite)); + + } } From 0efe55dc8e359c814599dba215ddbb5b5869c2c4 Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Thu, 22 Jun 2017 17:14:56 -0400 Subject: [PATCH 20/88] Code clean-up for pull request --- .../algorithms/mathematics/Primes.java | 73 ++++++---- .../mathematics/test/CoprimesTest.java | 8 +- .../mathematics/test/ExponentiationTest.java | 20 +-- .../test/{GCD.java => GCDTest.java} | 3 +- ...{Mathematics.java => MathematicsTest.java} | 7 +- .../mathematics/test/ModularArithmetic.java | 129 ------------------ .../test/ModularArithmeticTest.java | 129 ++++++++++++++++++ .../mathematics/test/PermutationsTest.java | 23 ++-- ...ests.java => RamerDouglasPeuckerTest.java} | 2 +- 9 files changed, 202 insertions(+), 192 deletions(-) rename test/com/jwetherell/algorithms/mathematics/test/{GCD.java => GCDTest.java} (98%) rename test/com/jwetherell/algorithms/mathematics/test/{Mathematics.java => MathematicsTest.java} (98%) delete mode 100644 test/com/jwetherell/algorithms/mathematics/test/ModularArithmetic.java create mode 100644 test/com/jwetherell/algorithms/mathematics/test/ModularArithmeticTest.java rename test/com/jwetherell/algorithms/mathematics/test/{RamerDouglasPeuckerTests.java => RamerDouglasPeuckerTest.java} (97%) diff --git a/src/com/jwetherell/algorithms/mathematics/Primes.java b/src/com/jwetherell/algorithms/mathematics/Primes.java index 8597c1dc..c6ec298c 100644 --- a/src/com/jwetherell/algorithms/mathematics/Primes.java +++ b/src/com/jwetherell/algorithms/mathematics/Primes.java @@ -5,35 +5,21 @@ import java.util.List; import java.util.Map; - /** - * isPrime() using the square root properties - *

- * 1 is not a prime. All primes except 2 are odd. All primes greater than 3 - * can be written in the form 6k+/-1. Any number n can have only one - * primefactor greater than n . The consequence for primality testing of a - * number n is: if we cannot find a number f less than or equal n that - * divides n then n is prime: the only primefactor of n is n itself - *
- * Sieve of Eratosthenes is an another way to check if number is prime. - *

- * https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes - *
- * Miller-Rabin primality test is the fastest way to check if number is prime. - * Regular version of this algorithm returns false when number is composite and true - * when number is probably prime. Here is implemented a deterministic version of this - * algorithm, witnesses are not randomized. Used set of witnesses guarantees that result - * will be correct for sure (not probably) for any number lower than 10^18. - *

- * https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test - *
- * * @author Justin Wetherell * @author Bartlomiej Drozd */ - public class Primes { + /** + * In number theory, the prime factors of a positive integer are the prime numbers that divide that integer exactly. The prime + * factorization of a positive integer is a list of the integer's prime factors, together with their multiplicities; the process + * of determining these factors is called integer factorization. The fundamental theorem of arithmetic says that every positive + * integer has a single unique prime factorization. + *

+ * https://en.wikipedia.org/wiki/Prime_factor + *
+ */ public static final Map getPrimeFactorization(long number) { Map map = new HashMap(); long n = number; @@ -62,6 +48,15 @@ public static final Map getPrimeFactorization(long number) { return map; } + /** + * isPrime() using the square root properties + *

+ * 1 is not a prime. All primes except 2 are odd. All primes greater than 3 + * can be written in the form 6k+/-1. Any number n can have only one + * prime factor greater than n . The consequence for primality testing of a + * number n is: if we cannot find a number f less than or equal n that + * divides n then n is prime: the only prime factor of n is n itself + **/ public static final boolean isPrime(long number) { if (number == 1) return false; @@ -88,16 +83,27 @@ public static final boolean isPrime(long number) { } /* - * Sieve of Eratosthenes + * Sieve of Eratosthenes, only has to be set once. */ private static boolean[] sieve = null; + /** + * In mathematics, the sieve of Eratosthenes is a simple, ancient algorithm for finding all prime numbers up to any given limit. + *

+ * It does so by iteratively marking as composite (i.e., not prime) the multiples of each prime, starting with the first prime + * number, 2. The multiples of a given prime are generated as a sequence of numbers starting from that prime, with constant + * difference between them that is equal to that prime. + *

+ * https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes + *
+ */ public static final boolean sieveOfEratosthenes(int number) { if (number == 1) { return false; } if (sieve == null || number >= sieve.length) { int start = 2; + if (sieve == null) { sieve = new boolean[number + 1]; } else if (number >= sieve.length) { @@ -115,9 +121,18 @@ public static final boolean sieveOfEratosthenes(int number) { return !sieve[number]; } - + /** + * Miller-Rabin primality test is the fastest way to check if number is prime. + * Regular version of this algorithm returns false when number is composite and true + * when number is probably prime. Here is implemented a deterministic version of this + * algorithm, witnesses are not randomized. Used set of witnesses guarantees that result + * will be correct for sure (not probably) for any number lower than 10^18. + *

+ * https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test + *
+ */ public static final boolean millerRabinTest(int number) { - List witnesses = Arrays.asList(2, 325, 9375, 28178, 450775, 9780504, 1795265022); + final List witnesses = Arrays.asList(2, 325, 9375, 28178, 450775, 9780504, 1795265022); if (number == 0 || number == 1) return false; @@ -130,11 +145,10 @@ public static final boolean millerRabinTest(int number) { maximumPowerOf2--; int d = (number - 1) / Exponentiation.fastRecursiveExponentiation(2, maximumPowerOf2); - boolean isPrime = true; - for (int a : witnesses) { - if (a > number) break; + if (a > number) + break; if (Exponentiation.fastRecursiveExponentiationModulo(a, d, number) != 1) { boolean isLocalPrime = false; for (int r = 0; r < maximumPowerOf2; r++) { @@ -150,7 +164,6 @@ public static final boolean millerRabinTest(int number) { } } - return isPrime; } } diff --git a/test/com/jwetherell/algorithms/mathematics/test/CoprimesTest.java b/test/com/jwetherell/algorithms/mathematics/test/CoprimesTest.java index f1bc8875..386aeda6 100644 --- a/test/com/jwetherell/algorithms/mathematics/test/CoprimesTest.java +++ b/test/com/jwetherell/algorithms/mathematics/test/CoprimesTest.java @@ -12,10 +12,10 @@ public class CoprimesTest { @Test public void totientTest(){ - List args = Arrays.asList(1L, 17L, 96L, 498L, 4182119424L); - List expected = Arrays.asList(1L, 16L, 32L, 164L, 1194891264L); - for(int i = 0; i < args.size(); i++) { + final List args = Arrays.asList(1L, 17L, 96L, 498L, 4182119424L); + final List expected = Arrays.asList(1L, 16L, 32L, 164L, 1194891264L); + + for(int i = 0; i < args.size(); i++) assertEquals(expected.get(i), Coprimes.getNumberOfCoprimes(args.get(i))); - } } } diff --git a/test/com/jwetherell/algorithms/mathematics/test/ExponentiationTest.java b/test/com/jwetherell/algorithms/mathematics/test/ExponentiationTest.java index 6f84cf57..11ef4d52 100644 --- a/test/com/jwetherell/algorithms/mathematics/test/ExponentiationTest.java +++ b/test/com/jwetherell/algorithms/mathematics/test/ExponentiationTest.java @@ -14,9 +14,9 @@ public class ExponentiationTest { @Test public void recusriveExponentiationTest() { - List baseList = Arrays.asList(1, 2, 4, 6, 8, 17, 24); - List exponentList = Arrays.asList(1000, 27, 14, 11, 10, 7, 5); - List expectedResultList = Arrays.asList(1, 134217728, 268435456, 362797056, 1073741824, 410338673, 7962624); + final List baseList = Arrays.asList(1, 2, 4, 6, 8, 17, 24); + final List exponentList = Arrays.asList(1000, 27, 14, 11, 10, 7, 5); + final List expectedResultList = Arrays.asList(1, 134217728, 268435456, 362797056, 1073741824, 410338673, 7962624); for (int i = 0; i < expectedResultList.size(); i++) assertEquals(expectedResultList.get(i), Exponentiation.recursiveExponentiation(baseList.get(i), exponentList.get(i))); @@ -24,9 +24,9 @@ public void recusriveExponentiationTest() { @Test public void fastRecusriveExponentiationTest() { - List baseList = Arrays.asList(1, 2, 4, 6, 8, 17, 24); - List exponentList = Arrays.asList(1000, 27, 14, 11, 10, 7, 5); - List expectedResultList = Arrays.asList(1, 134217728, 268435456, 362797056, 1073741824, 410338673, 7962624); + final List baseList = Arrays.asList(1, 2, 4, 6, 8, 17, 24); + final List exponentList = Arrays.asList(1000, 27, 14, 11, 10, 7, 5); + final List expectedResultList = Arrays.asList(1, 134217728, 268435456, 362797056, 1073741824, 410338673, 7962624); for (int i = 0; i < expectedResultList.size(); i++) assertEquals(expectedResultList.get(i), Exponentiation.fastRecursiveExponentiation(baseList.get(i), exponentList.get(i))); @@ -34,10 +34,10 @@ public void fastRecusriveExponentiationTest() { @Test public void fastRecusriveExponentiationModuloTest() { - List baseList = Arrays.asList(1, 2, 4, 6, 8, 17, 24, 2); - List exponentList = Arrays.asList(1000, 27, 14, 11, 10, 7, 5, 1089); - List divisorList = Arrays.asList(2, 6, 3, 2, 9, 11, 5, 2179); - List expectedResultList = Arrays.asList(1, 2, 1, 0, 1, 8, 4, 2178); + final List baseList = Arrays.asList(1, 2, 4, 6, 8, 17, 24, 2); + final List exponentList = Arrays.asList(1000, 27, 14, 11, 10, 7, 5, 1089); + final List divisorList = Arrays.asList(2, 6, 3, 2, 9, 11, 5, 2179); + final List expectedResultList = Arrays.asList(1, 2, 1, 0, 1, 8, 4, 2178); for (int i = 0; i < expectedResultList.size(); i++) assertEquals(expectedResultList.get(i), Exponentiation.fastRecursiveExponentiationModulo(baseList.get(i), exponentList.get(i), divisorList.get(i))); diff --git a/test/com/jwetherell/algorithms/mathematics/test/GCD.java b/test/com/jwetherell/algorithms/mathematics/test/GCDTest.java similarity index 98% rename from test/com/jwetherell/algorithms/mathematics/test/GCD.java rename to test/com/jwetherell/algorithms/mathematics/test/GCDTest.java index 7bdd8676..318e90f1 100644 --- a/test/com/jwetherell/algorithms/mathematics/test/GCD.java +++ b/test/com/jwetherell/algorithms/mathematics/test/GCDTest.java @@ -8,7 +8,7 @@ import com.jwetherell.algorithms.mathematics.GreatestCommonDivisor; -public class GCD { +public class GCDTest { @Test public void testRecursiveGCD() { @@ -37,5 +37,4 @@ public void testEuclideanGCD() { check = 5; assertTrue("Euclids GCD error. expected="+check+" got="+gcd, (gcd==check)); } - } diff --git a/test/com/jwetherell/algorithms/mathematics/test/Mathematics.java b/test/com/jwetherell/algorithms/mathematics/test/MathematicsTest.java similarity index 98% rename from test/com/jwetherell/algorithms/mathematics/test/Mathematics.java rename to test/com/jwetherell/algorithms/mathematics/test/MathematicsTest.java index 5d5fa1ee..c20381af 100644 --- a/test/com/jwetherell/algorithms/mathematics/test/Mathematics.java +++ b/test/com/jwetherell/algorithms/mathematics/test/MathematicsTest.java @@ -13,7 +13,7 @@ import com.jwetherell.algorithms.mathematics.Multiplication; import com.jwetherell.algorithms.mathematics.Primes; -public class Mathematics { +public class MathematicsTest { private static final int MIN = 1; private static final int MAX = 1000; @@ -299,15 +299,14 @@ public void sieveOfEratosthenes() { @Test public void millerRabin() { - List primeNumbers = Arrays.asList(2, 3, 7, 23, 2179, 25657, 34123); - List compositeNumbers = Arrays.asList(4, 9, 27, 2457, 26575, 34121); + final List primeNumbers = Arrays.asList(2, 3, 7, 23, 2179, 25657, 34123); + final List compositeNumbers = Arrays.asList(4, 9, 27, 2457, 26575, 34121); for (int prime : primeNumbers) assertTrue("Miller-Rabin test error. " + prime, Primes.millerRabinTest(prime)); for (int composite : compositeNumbers) assertFalse("Miller-Rabin test error. " + composite, Primes.millerRabinTest(composite)); - } } diff --git a/test/com/jwetherell/algorithms/mathematics/test/ModularArithmetic.java b/test/com/jwetherell/algorithms/mathematics/test/ModularArithmetic.java deleted file mode 100644 index a7733967..00000000 --- a/test/com/jwetherell/algorithms/mathematics/test/ModularArithmetic.java +++ /dev/null @@ -1,129 +0,0 @@ -package com.jwetherell.algorithms.mathematics.test; - -import com.jwetherell.algorithms.mathematics.Modular; -import org.junit.Test; -import static org.junit.Assert.*; - -public class ModularArithmetic { - - @Test - public void sumTest() { - assertEquals(4, - Modular.add(-3, 22, 5)); - - assertEquals(Long.MAX_VALUE-2, - Modular.add(Long.MAX_VALUE-1, Long.MAX_VALUE-1, Long.MAX_VALUE)); - - assertEquals(2, - Modular.add(1-Long.MAX_VALUE, 1-Long.MAX_VALUE, Long.MAX_VALUE)); - - - assertEquals(0, - Modular.add(Long.MAX_VALUE/2, Long.MAX_VALUE/2 + 1, Long.MAX_VALUE)); - - assertEquals(0, - Modular.add(-1000, -10000000, 10)); - - try { - Modular.add(1, 1,0); - assertTrue("No exception", false); - } catch (Exception ignored) { - } - } - - @Test - public void subtractTest() { - assertEquals(0, - Modular.subtract(-22, 3, 5)); - - assertEquals(Long.MAX_VALUE-1, - Modular.subtract(Long.MAX_VALUE-2, Long.MAX_VALUE-1, Long.MAX_VALUE)); - - assertEquals(Long.MAX_VALUE-1, - Modular.subtract(1-Long.MAX_VALUE, 2, Long.MAX_VALUE)); - - assertEquals(0, - Modular.subtract(-1000, -10000000, 10)); - - try { - Modular.subtract(1, 1,0); - assertTrue("No exception", false); - } catch (Exception ignored) { - } - } - - @Test - public void multiplyTest() { - assertEquals(10, - Modular.multiply(Long.MAX_VALUE-2, Long.MAX_VALUE-5, Long.MAX_VALUE)); - - assertEquals(3, - Modular.multiply(-5, -7, 32)); - - try { - Modular.multiply(1, 1,0); - assertTrue("No exception", false); - } catch (Exception ignored) { - } - - } - - @Test - public void powerTest() { - assertEquals(1, - Modular.pow(3, 1000000006, 1000000007)); - - assertEquals(8, - Modular.pow(2, 66, Long.MAX_VALUE)); - - assertEquals(1, - Modular.pow(123, 0, 1111)); - - assertEquals(0, - Modular.pow(0, 123, 2)); - - try { - Modular.pow(5, 0,5); - assertTrue("No exception", false); - } catch (Exception ignored) { - } - - try { - Modular.pow(5, -5,5); - assertTrue("No exception", false); - } catch (Exception ignored) { - } - - try { - Modular.pow(5, 5,0); - assertTrue("No exception", false); - } catch (Exception ignored) { - } - } - - @Test - public void divideTest() { - try { - Modular.divide(11, 6, 120); - assertTrue("No exception", false); - } catch (Exception ignored) { - } - - try { - Modular.divide(2, 2, 0); - assertTrue("No exception", false); - } catch (Exception ignored) { - } - - assertEquals(1, - Modular.divide(7, 7, 125)); - - assertEquals(97, - Modular.divide(Modular.multiply(97, 25, 1023), 25, 1023)); - - assertEquals(Long.MAX_VALUE-11, - Modular.divide(Modular.multiply(Long.MAX_VALUE-11, Long.MAX_VALUE-12, Long.MAX_VALUE), - Long.MAX_VALUE-12, - Long.MAX_VALUE)); - } -} \ No newline at end of file diff --git a/test/com/jwetherell/algorithms/mathematics/test/ModularArithmeticTest.java b/test/com/jwetherell/algorithms/mathematics/test/ModularArithmeticTest.java new file mode 100644 index 00000000..30c1acbc --- /dev/null +++ b/test/com/jwetherell/algorithms/mathematics/test/ModularArithmeticTest.java @@ -0,0 +1,129 @@ +package com.jwetherell.algorithms.mathematics.test; + +import com.jwetherell.algorithms.mathematics.Modular; +import org.junit.Test; +import static org.junit.Assert.*; + +public class ModularArithmeticTest { + + @Test + public void sumTest() { + assertEquals(4, Modular.add(-3, 22, 5)); + + assertEquals(Long.MAX_VALUE-2, Modular.add(Long.MAX_VALUE-1, Long.MAX_VALUE-1, Long.MAX_VALUE)); + + assertEquals(2, Modular.add(1-Long.MAX_VALUE, 1-Long.MAX_VALUE, Long.MAX_VALUE)); + + assertEquals(0, Modular.add(Long.MAX_VALUE/2, Long.MAX_VALUE/2 + 1, Long.MAX_VALUE)); + + assertEquals(0, Modular.add(-1000, -10000000, 10)); + + boolean exception = true; + try { + Modular.add(1, 1, 0); + exception = false; + } catch (IllegalArgumentException e) { + // ignore + } + assertTrue("Exception expected", exception); + } + + @Test + public void subtractTest() { + assertEquals(0, Modular.subtract(-22, 3, 5)); + + assertEquals(Long.MAX_VALUE-1, Modular.subtract(Long.MAX_VALUE-2, Long.MAX_VALUE-1, Long.MAX_VALUE)); + + assertEquals(Long.MAX_VALUE-1, Modular.subtract(1-Long.MAX_VALUE, 2, Long.MAX_VALUE)); + + assertEquals(0, Modular.subtract(-1000, -10000000, 10)); + + boolean exception = true; + try { + Modular.subtract(1, 1, 0); + exception = false; + } catch (IllegalArgumentException e) { + // ignore + } + assertTrue("Exception expected", exception); + } + + @Test + public void multiplyTest() { + assertEquals(10, Modular.multiply(Long.MAX_VALUE-2, Long.MAX_VALUE-5, Long.MAX_VALUE)); + + assertEquals(3, Modular.multiply(-5, -7, 32)); + + boolean exception = true; + try { + Modular.multiply(1, 1, 0); + exception = false; + } catch (IllegalArgumentException e) { + // ignore + } + assertTrue("Exception expected", exception); + } + + @Test + public void powerTest() { + assertEquals(1, Modular.pow(3, 1000000006, 1000000007)); + + assertEquals(8, Modular.pow(2, 66, Long.MAX_VALUE)); + + assertEquals(1, Modular.pow(123, 0, 1111)); + + assertEquals(0, Modular.pow(0, 123, 2)); + + boolean exception = true; + try { + Modular.pow(5, 0, 5); + exception = false; + } catch (IllegalArgumentException e) { + // ignore + } + assertTrue("Exception expected", exception); + + exception = true; + try { + Modular.pow(5, -5, 5); + exception = false; + } catch (IllegalArgumentException e) { + // ignore + } + assertTrue("Exception expected", exception); + + exception = true; + try { + Modular.pow(5, 5, 0); + exception = false; + } catch (IllegalArgumentException e) { + // ignore + } + assertTrue("Exception expected", exception); + } + + @Test + public void divideTest() { + assertEquals(1, Modular.divide(7, 7, 125)); + + assertEquals(97, Modular.divide(Modular.multiply(97, 25, 1023), 25, 1023)); + + assertEquals(Long.MAX_VALUE-11, Modular.divide(Modular.multiply(Long.MAX_VALUE-11, Long.MAX_VALUE-12, Long.MAX_VALUE), Long.MAX_VALUE-12, Long.MAX_VALUE)); + + boolean exception = true; + try { + Modular.divide(11, 6, 120); + } catch (IllegalArgumentException e) { + // ignore + } + assertTrue("Exception expected", exception); + + exception = true; + try { + Modular.divide(2, 2, 0); + } catch (ArithmeticException e) { + // ignore + } + assertTrue("Exception expected", exception); + } +} diff --git a/test/com/jwetherell/algorithms/mathematics/test/PermutationsTest.java b/test/com/jwetherell/algorithms/mathematics/test/PermutationsTest.java index 2eb60186..b0c27053 100644 --- a/test/com/jwetherell/algorithms/mathematics/test/PermutationsTest.java +++ b/test/com/jwetherell/algorithms/mathematics/test/PermutationsTest.java @@ -14,42 +14,42 @@ public class PermutationsTest { @Test public void test1NumberOfPermutations() { - Integer[] numbers = {1,2,3,4}; - int expectedNumberOfPermutations = 24; + final Integer[] numbers = {1,2,3,4}; + final int expectedNumberOfPermutations = 24; assertEquals(expectedNumberOfPermutations, (Permutations.getAllPermutations(numbers)).size()); } @Test public void test2NumberOfPermutations() { - Integer[] numbers = {3,4,2}; - int expectedNumberOfPermutations = 6; + final Integer[] numbers = {3,4,2}; + final int expectedNumberOfPermutations = 6; assertEquals(expectedNumberOfPermutations, (Permutations.getAllPermutations(numbers)).size()); } @Test public void test3NumberOfPermutations() { - Integer[] numbers = {3,4,2,5,4,9}; - int expectedNumberOfPermutations = 720; + final Integer[] numbers = {3,4,2,5,4,9}; + final int expectedNumberOfPermutations = 720; assertEquals(expectedNumberOfPermutations, (Permutations.getAllPermutations(numbers)).size()); } @Test public void testComparePermutations() { - Integer[] numbers = {4,2}; + final Integer[] numbers = {4,2}; - LinkedList firstPermutation = new LinkedList(); + final LinkedList firstPermutation = new LinkedList(); firstPermutation.add(4); firstPermutation.add(2); - LinkedList secondPermutation = new LinkedList(); + final LinkedList secondPermutation = new LinkedList(); secondPermutation.add(2); secondPermutation.add(4); - LinkedList> allPermutations = new LinkedList>(); + final LinkedList> allPermutations = new LinkedList>(); allPermutations.add(firstPermutation); allPermutations.add(secondPermutation); - List> result = Permutations.getAllPermutations(numbers); + final List> result = Permutations.getAllPermutations(numbers); assertTrue("allPermutations="+allPermutations+" result="+result, allPermutations.equals(result)); } @@ -71,5 +71,4 @@ public void testPermutation2() { Assert.assertTrue(list[17].equals("cdba")); Assert.assertTrue(list[23].equals("dcba")); } - } diff --git a/test/com/jwetherell/algorithms/mathematics/test/RamerDouglasPeuckerTests.java b/test/com/jwetherell/algorithms/mathematics/test/RamerDouglasPeuckerTest.java similarity index 97% rename from test/com/jwetherell/algorithms/mathematics/test/RamerDouglasPeuckerTests.java rename to test/com/jwetherell/algorithms/mathematics/test/RamerDouglasPeuckerTest.java index 59181e6e..08f1f71f 100644 --- a/test/com/jwetherell/algorithms/mathematics/test/RamerDouglasPeuckerTests.java +++ b/test/com/jwetherell/algorithms/mathematics/test/RamerDouglasPeuckerTest.java @@ -8,7 +8,7 @@ import com.jwetherell.algorithms.mathematics.RamerDouglasPeucker; -public class RamerDouglasPeuckerTests { +public class RamerDouglasPeuckerTest { @Test public void test1() { From 0c9cb11be2a0e61a48b227e70e3097e5d88b671b Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Thu, 22 Jun 2017 17:21:02 -0400 Subject: [PATCH 21/88] Merge branch 'master' of github.com:phishman3579/java-algorithms-implementation From 9ac3354389d00af996300c247ece82784696c925 Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Thu, 22 Jun 2017 17:22:30 -0400 Subject: [PATCH 22/88] Merge branch 'master' of github.com:phishman3579/java-algorithms-implementation From 0406142b5da1a3bd9a7a841c6cc86ae8740705bd Mon Sep 17 00:00:00 2001 From: kubaszar Date: Tue, 27 Jun 2017 18:02:53 +0200 Subject: [PATCH 23/88] Added Turbo Matching --- README.md | 4 +- .../algorithms/graph/TurboMatching.java | 112 +++++++++++++++ .../graph/test/TurboMatchingTest.java | 134 ++++++++++++++++++ 3 files changed, 249 insertions(+), 1 deletion(-) create mode 100644 src/com/jwetherell/algorithms/graph/TurboMatching.java create mode 100644 test/com/jwetherell/algorithms/graph/test/TurboMatchingTest.java diff --git a/README.md b/README.md index eeb6fb6c..c4a4f9b9 100644 --- a/README.md +++ b/README.md @@ -150,7 +150,9 @@ This is a collection of algorithms and data structures which I've implement over * Graph Traversal - [Depth First Traversal](src/com/jwetherell/algorithms/graph/DepthFirstTraversal.java) - [Breadth First Traversal](src/com/jwetherell/algorithms/graph/BreadthFirstTraversal.java) -* [Edmonds Karp](src/com/jwetherell/algorithms/graph/EdmondsKarp.java) +* [Edmonds Karp](src/com/jwetherell/algorithms/graph/EdmondsKarp.java) +* Matching + - [Turbo Matching](src/com/jwetherell/algorithms/graph/TurboMatching.java) ## Search * Get index of value in array diff --git a/src/com/jwetherell/algorithms/graph/TurboMatching.java b/src/com/jwetherell/algorithms/graph/TurboMatching.java new file mode 100644 index 00000000..b783c02b --- /dev/null +++ b/src/com/jwetherell/algorithms/graph/TurboMatching.java @@ -0,0 +1,112 @@ +package com.jwetherell.algorithms.graph; + +import com.jwetherell.algorithms.data_structures.Graph; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * In the mathematical discipline of graph theory, a matching or independent edge set + * in a graph is a set of edges without common vertices. In some matchings, all the vertices + * may incident with some edge of the matching, but this is not required and can only occur + * if the number of vertices is even. + *

+ * https://en.wikipedia.org/wiki/Matching_(graph_theory) + *
+ * @author Jakub Szarawarski + */ +public class TurboMatching { + + /** + * Computes maximum matching, using turbomatching algorithm based on augmenting paths with O(EV) complexity. + * + * @param graph bipartite graph + * @param parameter of graph on which network is based + * @return a MatchingResult class instance containg a map of mates for each paired vertex and number of pairs + */ + public static > MatchingResult getMaximumMatching(Graph graph){ + Map, Graph.Vertex> mate = new HashMap<>(); + + while(pathset(graph, mate)); + + return new MatchingResult<>(mate); + } + + /** + * Searches for an augmenting path for each unmatched vertex. + * + * @param graph bipartite graph + * @param mate map containing a mate for each matched vertex + * @return information if any augmenting path was found + */ + private static > boolean pathset(Graph graph, Map, Graph.Vertex> mate){ + Set> visited = new HashSet<>(); + + boolean result = false; + + for(Graph.Vertex vertex : graph.getVertices()){ + if (mate.containsKey(vertex) == false){ + if (path(graph, mate, visited, vertex)) + result = true; + } + } + + return result; + } + + /** + * Searches for an augmenting path for a vertex. + * Refreshes mates map appropriately. + * + * @param graph bipartite graph + * @param mate map containing a mate for each matched vertex + * @param visited set containing vertices visited in current pathset + * @param vertex regarded vertex + * @param parameter of graph on which network is based + * @return information if an augmenting path was found + */ + private static > boolean path(Graph graph, Map, Graph.Vertex> mate, Set> visited, Graph.Vertex vertex){ + if (visited.contains(vertex)) return false; + visited.add(vertex); + + for(Graph.Edge edge : vertex.getEdges()){ + + Graph.Vertex neighbour = edge.getFromVertex().equals(vertex) ? edge.getToVertex() : edge.getFromVertex(); + + if (mate.containsKey(neighbour) == false || path(graph, mate, visited, mate.get(neighbour))){ + mate.put(vertex, neighbour); + mate.put(neighbour, vertex); + return true; + } + } + + return false; + } + + + public static class MatchingResult>{ + private final Map, Graph.Vertex> mate; + private final int size; + + private MatchingResult(Map, Graph.Vertex> mate){ + this.mate = mate; + this.size = mate.size()/2; + } + + /** + * @return the number of edges in independent edge set + */ + public int getSize(){ + return this.size; + } + + /** + * @return a symetric map that contains a mate for each matched vertex + */ + public Map, Graph.Vertex> getMate(){ + return this.mate; + } + } +} diff --git a/test/com/jwetherell/algorithms/graph/test/TurboMatchingTest.java b/test/com/jwetherell/algorithms/graph/test/TurboMatchingTest.java new file mode 100644 index 00000000..cdb51acf --- /dev/null +++ b/test/com/jwetherell/algorithms/graph/test/TurboMatchingTest.java @@ -0,0 +1,134 @@ +package com.jwetherell.algorithms.graph.test; + +import com.jwetherell.algorithms.data_structures.Graph; +import com.jwetherell.algorithms.graph.TurboMatching; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.*; + + +public class TurboMatchingTest { + + private final Graph.Vertex v_a1 = new Graph.Vertex<>(1); + private final Graph.Vertex v_a2 = new Graph.Vertex<>(2); + private final Graph.Vertex v_a3 = new Graph.Vertex<>(3); + private final Graph.Vertex v_b1 = new Graph.Vertex<>(4); + private final Graph.Vertex v_b2 = new Graph.Vertex<>(5); + private final Graph.Vertex v_b3 = new Graph.Vertex<>(6); + + private List> vertices = new ArrayList<>(); + + { + vertices.add(v_a1); + vertices.add(v_a2); + vertices.add(v_a3); + vertices.add(v_b1); + vertices.add(v_b2); + vertices.add(v_b3); + } + @Test + public void testFullBipartiteGraph(){ + List> edges = new ArrayList<>(); + { + edges.add(new Graph.Edge<>(1, v_a1, v_b1)); + edges.add(new Graph.Edge<>(1, v_a1, v_b2)); + edges.add(new Graph.Edge<>(1, v_a1, v_b3)); + edges.add(new Graph.Edge<>(1, v_a2, v_b1)); + edges.add(new Graph.Edge<>(1, v_a2, v_b2)); + edges.add(new Graph.Edge<>(1, v_a2, v_b3)); + edges.add(new Graph.Edge<>(1, v_a3, v_b1)); + edges.add(new Graph.Edge<>(1, v_a3, v_b2)); + edges.add(new Graph.Edge<>(1, v_a3, v_b3)); + } + + final Graph graph = new Graph<>(vertices, edges); + + TurboMatching.MatchingResult matchingResult = TurboMatching.getMaximumMatching(graph); + assertTrue(matchingResult.getSize() == 3); + for(Graph.Vertex vertex : vertices){ + assertTrue(matchingResult.getMate().get(matchingResult.getMate().get(vertex)).equals(vertex)); + } + } + + @Test + public void testSingleEdgeForVertex(){ + List> edges = new ArrayList<>(); + { + edges.add(new Graph.Edge<>(1, v_a1, v_b1)); + edges.add(new Graph.Edge<>(1, v_a2, v_b2)); + edges.add(new Graph.Edge<>(1, v_a3, v_b3)); + } + + final Graph graph = new Graph<>(vertices, edges); + + TurboMatching.MatchingResult matchingResult = TurboMatching.getMaximumMatching(graph); + + assertTrue(matchingResult.getSize() == 3); + assertTrue(matchingResult.getMate().get(v_a1).equals(v_b1)); + assertTrue(matchingResult.getMate().get(v_a2).equals(v_b2)); + assertTrue(matchingResult.getMate().get(v_a3).equals(v_b3)); + assertTrue(matchingResult.getMate().get(v_b1).equals(v_a1)); + assertTrue(matchingResult.getMate().get(v_b2).equals(v_a2)); + assertTrue(matchingResult.getMate().get(v_b3).equals(v_a3)); + } + + @Test + public void testEmptyGraph(){ + List> edges = new ArrayList<>(); + { + } + + final Graph graph = new Graph<>(vertices, edges); + + TurboMatching.MatchingResult matchingResult = TurboMatching.getMaximumMatching(graph); + + assertTrue(matchingResult.getSize() == 0); + assertTrue(matchingResult.getMate().isEmpty()); + } + + @Test + public void testTwoMatched(){ + List> edges = new ArrayList<>(); + { + edges.add(new Graph.Edge<>(1, v_a1, v_b1)); + edges.add(new Graph.Edge<>(1, v_a1, v_b3)); + edges.add(new Graph.Edge<>(1, v_a2, v_b2)); + edges.add(new Graph.Edge<>(1, v_a3, v_b2)); + } + + final Graph graph = new Graph<>(vertices, edges); + TurboMatching.MatchingResult matchingResult = TurboMatching.getMaximumMatching(graph); + + assertTrue(matchingResult.getSize() == 2); + assertTrue(matchingResult.getMate().containsKey(v_a1)); + assertTrue(matchingResult.getMate().containsKey(v_b2)); + assertTrue(matchingResult.getMate().containsValue(v_a1)); + assertTrue(matchingResult.getMate().containsValue(v_b2)); + } + + @Test + public void testOneMatched(){ + List> edges = new ArrayList<>(); + { + edges.add(new Graph.Edge<>(1, v_a1, v_b1)); + edges.add(new Graph.Edge<>(1, v_a1, v_b2)); + edges.add(new Graph.Edge<>(1, v_a1, v_b3)); + } + + final Graph graph = new Graph<>(vertices, edges); + TurboMatching.MatchingResult matchingResult = TurboMatching.getMaximumMatching(graph); + + assertTrue(matchingResult.getSize() == 1); + assertTrue(matchingResult.getMate().containsKey(v_a1)); + assertTrue(matchingResult.getMate().containsValue(v_a1)); + assertFalse(matchingResult.getMate().containsKey(v_a2)); + assertFalse(matchingResult.getMate().containsValue(v_a2)); + assertFalse(matchingResult.getMate().containsKey(v_a3)); + assertFalse(matchingResult.getMate().containsValue(v_a3)); + } + + +} \ No newline at end of file From a182542104506740631187154924a58d93e095ff Mon Sep 17 00:00:00 2001 From: kubaszar Date: Tue, 27 Jun 2017 20:53:59 +0200 Subject: [PATCH 24/88] Diamond operator fixed --- .../algorithms/graph/TurboMatching.java | 6 +- .../graph/test/TurboMatchingTest.java | 72 +++++++++---------- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/src/com/jwetherell/algorithms/graph/TurboMatching.java b/src/com/jwetherell/algorithms/graph/TurboMatching.java index b783c02b..88120c82 100644 --- a/src/com/jwetherell/algorithms/graph/TurboMatching.java +++ b/src/com/jwetherell/algorithms/graph/TurboMatching.java @@ -27,11 +27,11 @@ public class TurboMatching { * @return a MatchingResult class instance containg a map of mates for each paired vertex and number of pairs */ public static > MatchingResult getMaximumMatching(Graph graph){ - Map, Graph.Vertex> mate = new HashMap<>(); + Map, Graph.Vertex> mate = new HashMap, Graph.Vertex>(); while(pathset(graph, mate)); - return new MatchingResult<>(mate); + return new MatchingResult(mate); } /** @@ -42,7 +42,7 @@ public static > MatchingResult getMaximumMatching(Gra * @return information if any augmenting path was found */ private static > boolean pathset(Graph graph, Map, Graph.Vertex> mate){ - Set> visited = new HashSet<>(); + Set> visited = new HashSet>(); boolean result = false; diff --git a/test/com/jwetherell/algorithms/graph/test/TurboMatchingTest.java b/test/com/jwetherell/algorithms/graph/test/TurboMatchingTest.java index cdb51acf..5e9be687 100644 --- a/test/com/jwetherell/algorithms/graph/test/TurboMatchingTest.java +++ b/test/com/jwetherell/algorithms/graph/test/TurboMatchingTest.java @@ -12,14 +12,14 @@ public class TurboMatchingTest { - private final Graph.Vertex v_a1 = new Graph.Vertex<>(1); - private final Graph.Vertex v_a2 = new Graph.Vertex<>(2); - private final Graph.Vertex v_a3 = new Graph.Vertex<>(3); - private final Graph.Vertex v_b1 = new Graph.Vertex<>(4); - private final Graph.Vertex v_b2 = new Graph.Vertex<>(5); - private final Graph.Vertex v_b3 = new Graph.Vertex<>(6); + private final Graph.Vertex v_a1 = new Graph.Vertex(1); + private final Graph.Vertex v_a2 = new Graph.Vertex(2); + private final Graph.Vertex v_a3 = new Graph.Vertex(3); + private final Graph.Vertex v_b1 = new Graph.Vertex(4); + private final Graph.Vertex v_b2 = new Graph.Vertex(5); + private final Graph.Vertex v_b3 = new Graph.Vertex(6); - private List> vertices = new ArrayList<>(); + private List> vertices = new ArrayList>(); { vertices.add(v_a1); @@ -31,20 +31,20 @@ public class TurboMatchingTest { } @Test public void testFullBipartiteGraph(){ - List> edges = new ArrayList<>(); + List> edges = new ArrayList>(); { - edges.add(new Graph.Edge<>(1, v_a1, v_b1)); - edges.add(new Graph.Edge<>(1, v_a1, v_b2)); - edges.add(new Graph.Edge<>(1, v_a1, v_b3)); - edges.add(new Graph.Edge<>(1, v_a2, v_b1)); - edges.add(new Graph.Edge<>(1, v_a2, v_b2)); - edges.add(new Graph.Edge<>(1, v_a2, v_b3)); - edges.add(new Graph.Edge<>(1, v_a3, v_b1)); - edges.add(new Graph.Edge<>(1, v_a3, v_b2)); - edges.add(new Graph.Edge<>(1, v_a3, v_b3)); + edges.add(new Graph.Edge(1, v_a1, v_b1)); + edges.add(new Graph.Edge(1, v_a1, v_b2)); + edges.add(new Graph.Edge(1, v_a1, v_b3)); + edges.add(new Graph.Edge(1, v_a2, v_b1)); + edges.add(new Graph.Edge(1, v_a2, v_b2)); + edges.add(new Graph.Edge(1, v_a2, v_b3)); + edges.add(new Graph.Edge(1, v_a3, v_b1)); + edges.add(new Graph.Edge(1, v_a3, v_b2)); + edges.add(new Graph.Edge(1, v_a3, v_b3)); } - final Graph graph = new Graph<>(vertices, edges); + final Graph graph = new Graph(vertices, edges); TurboMatching.MatchingResult matchingResult = TurboMatching.getMaximumMatching(graph); assertTrue(matchingResult.getSize() == 3); @@ -55,14 +55,14 @@ public void testFullBipartiteGraph(){ @Test public void testSingleEdgeForVertex(){ - List> edges = new ArrayList<>(); + List> edges = new ArrayList>(); { - edges.add(new Graph.Edge<>(1, v_a1, v_b1)); - edges.add(new Graph.Edge<>(1, v_a2, v_b2)); - edges.add(new Graph.Edge<>(1, v_a3, v_b3)); + edges.add(new Graph.Edge(1, v_a1, v_b1)); + edges.add(new Graph.Edge(1, v_a2, v_b2)); + edges.add(new Graph.Edge(1, v_a3, v_b3)); } - final Graph graph = new Graph<>(vertices, edges); + final Graph graph = new Graph(vertices, edges); TurboMatching.MatchingResult matchingResult = TurboMatching.getMaximumMatching(graph); @@ -77,11 +77,11 @@ public void testSingleEdgeForVertex(){ @Test public void testEmptyGraph(){ - List> edges = new ArrayList<>(); + List> edges = new ArrayList>(); { } - final Graph graph = new Graph<>(vertices, edges); + final Graph graph = new Graph(vertices, edges); TurboMatching.MatchingResult matchingResult = TurboMatching.getMaximumMatching(graph); @@ -91,15 +91,15 @@ public void testEmptyGraph(){ @Test public void testTwoMatched(){ - List> edges = new ArrayList<>(); + List> edges = new ArrayList>(); { - edges.add(new Graph.Edge<>(1, v_a1, v_b1)); - edges.add(new Graph.Edge<>(1, v_a1, v_b3)); - edges.add(new Graph.Edge<>(1, v_a2, v_b2)); - edges.add(new Graph.Edge<>(1, v_a3, v_b2)); + edges.add(new Graph.Edge(1, v_a1, v_b1)); + edges.add(new Graph.Edge(1, v_a1, v_b3)); + edges.add(new Graph.Edge(1, v_a2, v_b2)); + edges.add(new Graph.Edge(1, v_a3, v_b2)); } - final Graph graph = new Graph<>(vertices, edges); + final Graph graph = new Graph(vertices, edges); TurboMatching.MatchingResult matchingResult = TurboMatching.getMaximumMatching(graph); assertTrue(matchingResult.getSize() == 2); @@ -111,14 +111,14 @@ public void testTwoMatched(){ @Test public void testOneMatched(){ - List> edges = new ArrayList<>(); + List> edges = new ArrayList>(); { - edges.add(new Graph.Edge<>(1, v_a1, v_b1)); - edges.add(new Graph.Edge<>(1, v_a1, v_b2)); - edges.add(new Graph.Edge<>(1, v_a1, v_b3)); + edges.add(new Graph.Edge(1, v_a1, v_b1)); + edges.add(new Graph.Edge(1, v_a1, v_b2)); + edges.add(new Graph.Edge(1, v_a1, v_b3)); } - final Graph graph = new Graph<>(vertices, edges); + final Graph graph = new Graph(vertices, edges); TurboMatching.MatchingResult matchingResult = TurboMatching.getMaximumMatching(graph); assertTrue(matchingResult.getSize() == 1); From c7f24c3055b7dad1a23da3bc5c2b9b62a9277e71 Mon Sep 17 00:00:00 2001 From: kubaszar Date: Tue, 27 Jun 2017 22:12:29 +0200 Subject: [PATCH 25/88] Added Suffix Array --- README.md | 1 + .../data_structures/SuffixArray.java | 170 ++++++++++++++++++ .../data_structures/test/SuffixArrayTest.java | 45 +++++ 3 files changed, 216 insertions(+) create mode 100644 src/com/jwetherell/algorithms/data_structures/SuffixArray.java create mode 100644 test/com/jwetherell/algorithms/data_structures/test/SuffixArrayTest.java diff --git a/README.md b/README.md index c4a4f9b9..c8a64916 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,7 @@ This is a collection of algorithms and data structures which I've implement over * [Skip List](src/com/jwetherell/algorithms/data_structures/SkipList.java) * [Splay Tree](src/com/jwetherell/algorithms/data_structures/SplayTree.java) * [Stack [backed by an array or a linked list]](src/com/jwetherell/algorithms/data_structures/Stack.java) +* [Suffix Array](src/com/jwetherell/algorithms/data_structures/SuffixArray.java) * [Suffix Tree (Ukkonen's algorithm)](src/com/jwetherell/algorithms/data_structures/SuffixTree.java) * [Suffix Trie [backed by a Trie]](src/com/jwetherell/algorithms/data_structures/SuffixTrie.java) * [Treap](src/com/jwetherell/algorithms/data_structures/Treap.java) diff --git a/src/com/jwetherell/algorithms/data_structures/SuffixArray.java b/src/com/jwetherell/algorithms/data_structures/SuffixArray.java new file mode 100644 index 00000000..10507afd --- /dev/null +++ b/src/com/jwetherell/algorithms/data_structures/SuffixArray.java @@ -0,0 +1,170 @@ +package com.jwetherell.algorithms.data_structures; + +import java.util.ArrayList; +import java.util.Collections; + +/** + * In computer science, a suffix array is a sorted array of all suffixes of a string. + * It is a data structure used, among others, in full text indices, data compression + * algorithms and within the field of bibliometrics. + * + * https://en.wikipedia.org/wiki/Suffix_array + * + * This implementation returns starting indexes instead of full suffixes + * + * @author Jakub Szarawarski + */ +public class SuffixArray { + private static final char DEFAULT_END_SEQ_CHAR = '$'; + private char END_SEQ_CHAR; + private String string; + private ArrayList suffixArray = null; + private ArrayList KMRarray = null; + + public SuffixArray(CharSequence sequence) { + this(sequence, DEFAULT_END_SEQ_CHAR); + } + + public SuffixArray(CharSequence sequence, char endChar) { + END_SEQ_CHAR = endChar; + string = buildStringWithEndChar(sequence); + } + + public ArrayList getSuffixArray() { + if(suffixArray == null){ + KMRalgorithm(); + } + return suffixArray; + } + + /** + * @return inverted suffix array + */ + public ArrayList getKMRarray() { + if (KMRarray == null) { + KMRalgorithm(); + } + return KMRarray; + } + + /** + * Creates suffix array using KMR algorithm with O(n log^2 n) complexity. + * + * For radius r: + * KMR[i] == k, + * when string[i..i+r-1] is kth r-letter substring of string sorted lexicographically + * KMR is counted for radius = 1,2,4,8 ... + * KMR for radius bigger than string length is the inverted suffix array + */ + private void KMRalgorithm() { + int length = string.length(); + + ArrayList KMR = getBasicKMR(length); + ArrayList KMRinvertedList = new ArrayList(); + + int radius = 1; + + while(radius < length){ + KMRinvertedList = getKMRinvertedList(KMR, radius, length); + KMR = getKMR(KMRinvertedList, radius, length); + radius *= 2; + } + + KMRarray = new ArrayList(KMR.subList(0, length)); + suffixArray = new ArrayList(); + KMRinvertedList.forEach(k -> suffixArray.add(k.index)); + } + + /** + * Creates KMR array for new radius from nearly inverted array. + * Elements from inverted array need to be grouped by substring tey represent. + * + * @param KMRinvertedList indexes are nearly inverted KMR array + * @param length string length + * @return KMR array for new radius + */ + private ArrayList getKMR(ArrayList KMRinvertedList, int radius, int length) { + ArrayList KMR = new ArrayList(length*2); + for(int i=0; i<2*length; i++) KMR.add(-1); + + int counter = 0; + for(int i=0; i0 && substringsAreEqual(KMRinvertedList, i)) + counter++; + KMR.set(KMRinvertedList.get(i).index, counter); + } + + return KMR; + } + + private boolean substringsAreEqual(ArrayList KMRinvertedList, int i) { + return KMRinvertedList.get(i-1).beginKMR.equals(KMRinvertedList.get(i).beginKMR) == false || + KMRinvertedList.get(i-1).endKMR.equals(KMRinvertedList.get(i).endKMR) == false; + } + + /** + * helper method to create KMR array for radius = radius from KMR array for radius = radius/2 + * + * @param KMR KMR array for radius = radius/2 + * @param radius new radius + * @param length string length + * @return list of KMRsWithIndex which indexes are nearly inverted KMR array + */ + private ArrayList getKMRinvertedList(ArrayList KMR, int radius, int length) { + ArrayList KMRinvertedList = new ArrayList(); + + for(int i=0; i { + if(A.beginKMR.equals(B.beginKMR) == false){ + return A.beginKMR.compareTo(B.beginKMR); + } + if(A.endKMR.equals(B.endKMR) == false){ + return A.endKMR.compareTo(B.endKMR); + } + return A.index.compareTo(B.index); + }); + + return KMRinvertedList; + } + + /** + * KMR array for radius=1, instead of initial natural numbers ascii codes are used + * + * @param length length of string + * @return pseudo KMR array for radius=1 + */ + private ArrayList getBasicKMR(int length) { + ArrayList result = new ArrayList(length*2); + char[] characters = string.toCharArray(); + for(int i=0; i suffixTree = new SuffixTree(string); + + Set suffixSet = suffixTree.getSuffixes(); + ArrayList suffixArray = suffixArrayBuilder.getSuffixArray(); + + int length = string.length(); + int i=0; + for(String suffix : suffixSet){ + String substring = string.substring(suffixArray.get(i++)); + assertTrue(suffix.equals(substring)); + } + } + + @Test + public void testKMRarray(){ + String string = "aasfaasdsadasdfasdasdasdasfdasfassdfas"; + + SuffixArray suffixArrayBuilder = new SuffixArray(string); + ArrayList suffixArray = suffixArrayBuilder.getSuffixArray(); + ArrayList KMRarray = suffixArrayBuilder.getKMRarray(); + + int length = string.length(); + for(int i=0; i Date: Tue, 27 Jun 2017 23:54:27 +0200 Subject: [PATCH 26/88] Lambdas removed --- .../data_structures/SuffixArray.java | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/com/jwetherell/algorithms/data_structures/SuffixArray.java b/src/com/jwetherell/algorithms/data_structures/SuffixArray.java index 10507afd..2e93faeb 100644 --- a/src/com/jwetherell/algorithms/data_structures/SuffixArray.java +++ b/src/com/jwetherell/algorithms/data_structures/SuffixArray.java @@ -2,6 +2,7 @@ import java.util.ArrayList; import java.util.Collections; +import java.util.Comparator; /** * In computer science, a suffix array is a sorted array of all suffixes of a string. @@ -72,7 +73,9 @@ private void KMRalgorithm() { KMRarray = new ArrayList(KMR.subList(0, length)); suffixArray = new ArrayList(); - KMRinvertedList.forEach(k -> suffixArray.add(k.index)); + for(KMRsWithIndex kmr : KMRinvertedList){ + suffixArray.add(kmr.index); + } } /** @@ -117,14 +120,17 @@ private ArrayList getKMRinvertedList(ArrayList KMR, int KMRinvertedList.add(new KMRsWithIndex(KMR.get(i), KMR.get(i+radius), i)); } - Collections.sort(KMRinvertedList, (A, B) -> { - if(A.beginKMR.equals(B.beginKMR) == false){ - return A.beginKMR.compareTo(B.beginKMR); - } - if(A.endKMR.equals(B.endKMR) == false){ - return A.endKMR.compareTo(B.endKMR); + Collections.sort(KMRinvertedList, new Comparator() { + @Override + public int compare(KMRsWithIndex A, KMRsWithIndex B) { + if (A.beginKMR.equals(B.beginKMR) == false) { + return A.beginKMR.compareTo(B.beginKMR); + } + if (A.endKMR.equals(B.endKMR) == false) { + return A.endKMR.compareTo(B.endKMR); + } + return A.index.compareTo(B.index); } - return A.index.compareTo(B.index); }); return KMRinvertedList; From 7f5ccd914380d279312c966bf251bad33296943f Mon Sep 17 00:00:00 2001 From: kubaszar Date: Wed, 28 Jun 2017 02:31:55 +0200 Subject: [PATCH 27/88] Added LCP Array Tests --- .../data_structures/test/LCPArrayTest.java | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 test/com/jwetherell/algorithms/data_structures/test/LCPArrayTest.java diff --git a/test/com/jwetherell/algorithms/data_structures/test/LCPArrayTest.java b/test/com/jwetherell/algorithms/data_structures/test/LCPArrayTest.java new file mode 100644 index 00000000..3bfbe3fa --- /dev/null +++ b/test/com/jwetherell/algorithms/data_structures/test/LCPArrayTest.java @@ -0,0 +1,52 @@ +package com.jwetherell.algorithms.data_structures.test; + +import com.jwetherell.algorithms.data_structures.LCPArray; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; + +import static org.junit.Assert.*; + +public class LCPArrayTest { + + @Test + public void smallTest(){ + String string = "asdasdd"; + LCPArray LCPArrayBuilder = new LCPArray(string); + ArrayList LCPArray = LCPArrayBuilder.getLCPArray(); + ArrayList result = new ArrayList(); + + result.addAll(Arrays.asList(null, 0, 3, 0, 1, 1, 0, 2)); + + assertEquals(LCPArray, result); + } + + @Test + public void longTest(){ + + String string = "aasfaasdsadasdfasdasdasdasfdasfassdfas"; + LCPArray LCPArrayBuilder = new LCPArray(string); + ArrayList LCPArray = LCPArrayBuilder.getLCPArray(); + ArrayList result = new ArrayList(); + + result.addAll(Arrays.asList(null, 0, 3, 1, 1, 2, 8, 5, 3, 3, 2, 4, 3, 2, 0, + 6, 4, 3, 4, 1, 4, 1, 0, 2, 3, 3, 1, 0, 1, 1, 7, 4, 2, 5, 2, 1, 3, 2, 1)); + + assertEquals(LCPArray, result); + } + + @Test + public void singleLetterTest(){ + + String string = "aaaaaaaaaaaa"; + LCPArray LCPArrayBuilder = new LCPArray(string); + ArrayList LCPArray = LCPArrayBuilder.getLCPArray(); + ArrayList result = new ArrayList(); + + result.addAll(Arrays.asList(null , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)); + + assertEquals(LCPArray, result); + } + +} \ No newline at end of file From 8a951a7ba500a23b2e47371008bc0a4a463a187a Mon Sep 17 00:00:00 2001 From: kubaszar Date: Wed, 28 Jun 2017 02:32:27 +0200 Subject: [PATCH 28/88] Added LCP Array --- .../algorithms/data_structures/LCPArray.java | 84 +++++++++++++++++++ .../data_structures/SuffixArray.java | 4 + 2 files changed, 88 insertions(+) create mode 100644 src/com/jwetherell/algorithms/data_structures/LCPArray.java diff --git a/src/com/jwetherell/algorithms/data_structures/LCPArray.java b/src/com/jwetherell/algorithms/data_structures/LCPArray.java new file mode 100644 index 00000000..9726fc41 --- /dev/null +++ b/src/com/jwetherell/algorithms/data_structures/LCPArray.java @@ -0,0 +1,84 @@ +package com.jwetherell.algorithms.data_structures; + +import java.util.ArrayList; + +/** + * In computer science, the longest common prefix array (LCP array) is an auxiliary + * data structure to the suffix array. It stores the lengths of the longest common + * prefixes (LCPs) between all pairs of consecutive suffixes in a sorted suffix array. + * + * https://en.wikipedia.org/wiki/LCP_array + * + * @author Jakub Szarawarski + */ +public class LCPArray { + private static final char DEFAULT_END_SEQ_CHAR = '$'; + private char END_SEQ_CHAR; + + private SuffixArray suffixArrayBuilder; + + private ArrayList LCP; + + public LCPArray(CharSequence sequence){ + this(sequence, DEFAULT_END_SEQ_CHAR); + } + + public LCPArray(CharSequence sequence, char endChar) { + END_SEQ_CHAR = endChar; + suffixArrayBuilder = new SuffixArray(sequence, endChar); + } + + public ArrayList getLCPArray() { + if(LCP == null){ + LCPAlgorithm(); + } + return LCP; + } + + private void LCPAlgorithm() { + ArrayList LCPR = getLCPR(); + getLCPfromLCPR(LCPR); + } + + private ArrayList getLCPR() { + ArrayList KMRArray = suffixArrayBuilder.getKMRarray(); + ArrayList suffixArray = suffixArrayBuilder.getSuffixArray(); + String string = suffixArrayBuilder.getString(); + int length = KMRArray.size(); + + ArrayList LCPR = new ArrayList(); // helper array, LCP[i] = LCPR[suffixArray[i]] + + int startingValue = 0; + + for(int i=0; i 0 ? LCPRValue-1 : 0; + } + } + + return LCPR; + } + + private void getLCPfromLCPR(ArrayList LCPR) { + ArrayList suffixArray = suffixArrayBuilder.getSuffixArray(); + int length = suffixArray.size(); + + LCP = new ArrayList(); + LCP.add(null); //no value for LCP[0] + + for(int i=1; i getKMRarray() { return KMRarray; } + public String getString(){ + return string; + } + /** * Creates suffix array using KMR algorithm with O(n log^2 n) complexity. * From 9ccb6d478a53fc9015f94d1826cd4c5eeb6b4cc3 Mon Sep 17 00:00:00 2001 From: kubaszar Date: Wed, 28 Jun 2017 02:35:44 +0200 Subject: [PATCH 29/88] Added LCP Array - README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c8a64916..930ae6a0 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ This is a collection of algorithms and data structures which I've implement over * [Implicit Key Treap](src/com/jwetherell/algorithms/data_structures/ImplicitKeyTreap.java) * [KD Tree (k-dimensional tree or k-d tree)](src/com/jwetherell/algorithms/data_structures/KDTree.java) * [List [backed by an array or a linked list]](src/com/jwetherell/algorithms/data_structures/List.java) +* [LCP Array (Longest Common Prefix) [backed by a Suffix Array]](src/com/jwetherell/algorithms/data_structures/LCPArray.java) * [Matrix](src/com/jwetherell/algorithms/data_structures/Matrix.java) * [Patricia Trie](src/com/jwetherell/algorithms/data_structures/PatriciaTrie.java) * [Quad-Tree (Point-Region or MX-CIF)](src/com/jwetherell/algorithms/data_structures/QuadTree.java) From 2f826ce467022bfeedca194221ff0ef11e9d5775 Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Mon, 3 Jul 2017 11:40:17 -0400 Subject: [PATCH 30/88] Code cleanup --- .../algorithms/data_structures/KdTree.java | 2 +- .../algorithms/data_structures/LCPArray.java | 49 +++++----- .../data_structures/SuffixArray.java | 92 +++++++++---------- .../data_structures/test/SuffixArrayTest.java | 1 - 4 files changed, 66 insertions(+), 78 deletions(-) diff --git a/src/com/jwetherell/algorithms/data_structures/KdTree.java b/src/com/jwetherell/algorithms/data_structures/KdTree.java index 0ed727e7..9fecb819 100644 --- a/src/com/jwetherell/algorithms/data_structures/KdTree.java +++ b/src/com/jwetherell/algorithms/data_structures/KdTree.java @@ -21,7 +21,7 @@ * useful data structure for several applications, such as searches involving a * multidimensional search key (e.g. range searches and nearest neighbor * searches). k-d trees are a special case of binary space partitioning trees. - * + *
* @author Justin Wetherell * @see K-d_tree (Wikipedia) */ diff --git a/src/com/jwetherell/algorithms/data_structures/LCPArray.java b/src/com/jwetherell/algorithms/data_structures/LCPArray.java index 9726fc41..88d299c8 100644 --- a/src/com/jwetherell/algorithms/data_structures/LCPArray.java +++ b/src/com/jwetherell/algorithms/data_structures/LCPArray.java @@ -6,17 +6,18 @@ * In computer science, the longest common prefix array (LCP array) is an auxiliary * data structure to the suffix array. It stores the lengths of the longest common * prefixes (LCPs) between all pairs of consecutive suffixes in a sorted suffix array. - * + *

* https://en.wikipedia.org/wiki/LCP_array - * + *
* @author Jakub Szarawarski + * @author Justin Wetherell */ public class LCPArray { + private static final char DEFAULT_END_SEQ_CHAR = '$'; - private char END_SEQ_CHAR; + private char END_SEQ_CHAR; private SuffixArray suffixArrayBuilder; - private ArrayList LCP; public LCPArray(CharSequence sequence){ @@ -25,43 +26,37 @@ public LCPArray(CharSequence sequence){ public LCPArray(CharSequence sequence, char endChar) { END_SEQ_CHAR = endChar; - suffixArrayBuilder = new SuffixArray(sequence, endChar); + suffixArrayBuilder = new SuffixArray(sequence, END_SEQ_CHAR); } public ArrayList getLCPArray() { - if(LCP == null){ + if (LCP == null) LCPAlgorithm(); - } return LCP; } private void LCPAlgorithm() { - ArrayList LCPR = getLCPR(); + final ArrayList LCPR = getLCPR(); getLCPfromLCPR(LCPR); } private ArrayList getLCPR() { - ArrayList KMRArray = suffixArrayBuilder.getKMRarray(); - ArrayList suffixArray = suffixArrayBuilder.getSuffixArray(); - String string = suffixArrayBuilder.getString(); - int length = KMRArray.size(); - - ArrayList LCPR = new ArrayList(); // helper array, LCP[i] = LCPR[suffixArray[i]] + final ArrayList KMRArray = suffixArrayBuilder.getKMRarray(); + final ArrayList suffixArray = suffixArrayBuilder.getSuffixArray(); + final String string = suffixArrayBuilder.getString(); + final int length = KMRArray.size(); + final ArrayList LCPR = new ArrayList(); // helper array, LCP[i] = LCPR[suffixArray[i]] int startingValue = 0; - - for(int i=0; i 0 ? LCPRValue-1 : 0; } @@ -71,14 +66,12 @@ private ArrayList getLCPR() { } private void getLCPfromLCPR(ArrayList LCPR) { - ArrayList suffixArray = suffixArrayBuilder.getSuffixArray(); - int length = suffixArray.size(); + final ArrayList suffixArray = suffixArrayBuilder.getSuffixArray(); + final int length = suffixArray.size(); LCP = new ArrayList(); LCP.add(null); //no value for LCP[0] - - for(int i=1; i * https://en.wikipedia.org/wiki/Suffix_array - * - * This implementation returns starting indexes instead of full suffixes - * + *

+ * NOTE: This implementation returns starting indexes instead of full suffixes + *
* @author Jakub Szarawarski + * @author Justin Wetherell */ public class SuffixArray { + + private static final StringBuilder STRING_BUILDER = new StringBuilder(); private static final char DEFAULT_END_SEQ_CHAR = '$'; + private char END_SEQ_CHAR; private String string; private ArrayList suffixArray = null; @@ -32,9 +36,8 @@ public SuffixArray(CharSequence sequence, char endChar) { } public ArrayList getSuffixArray() { - if(suffixArray == null){ + if (suffixArray == null) KMRalgorithm(); - } return suffixArray; } @@ -42,9 +45,8 @@ public ArrayList getSuffixArray() { * @return inverted suffix array */ public ArrayList getKMRarray() { - if (KMRarray == null) { + if (KMRarray == null) KMRalgorithm(); - } return KMRarray; } @@ -62,24 +64,22 @@ public String getString(){ * KMR for radius bigger than string length is the inverted suffix array */ private void KMRalgorithm() { - int length = string.length(); + final int length = string.length(); - ArrayList KMR = getBasicKMR(length); ArrayList KMRinvertedList = new ArrayList(); + ArrayList KMR = getBasicKMR(length); int radius = 1; - - while(radius < length){ + while (radius < length) { KMRinvertedList = getKMRinvertedList(KMR, radius, length); - KMR = getKMR(KMRinvertedList, radius, length); + KMR = getKMR(KMRinvertedList, length); radius *= 2; } KMRarray = new ArrayList(KMR.subList(0, length)); suffixArray = new ArrayList(); - for(KMRsWithIndex kmr : KMRinvertedList){ + for (KMRsWithIndex kmr : KMRinvertedList) suffixArray.add(kmr.index); - } } /** @@ -90,12 +90,13 @@ private void KMRalgorithm() { * @param length string length * @return KMR array for new radius */ - private ArrayList getKMR(ArrayList KMRinvertedList, int radius, int length) { - ArrayList KMR = new ArrayList(length*2); - for(int i=0; i<2*length; i++) KMR.add(-1); + private ArrayList getKMR(ArrayList KMRinvertedList, int length) { + final ArrayList KMR = new ArrayList(length*2); + for (int i=0; i<2*length; i++) + KMR.add(-1); int counter = 0; - for(int i=0; i0 && substringsAreEqual(KMRinvertedList, i)) counter++; KMR.set(KMRinvertedList.get(i).index, counter); @@ -105,8 +106,8 @@ private ArrayList getKMR(ArrayList KMRinvertedList, int } private boolean substringsAreEqual(ArrayList KMRinvertedList, int i) { - return KMRinvertedList.get(i-1).beginKMR.equals(KMRinvertedList.get(i).beginKMR) == false || - KMRinvertedList.get(i-1).endKMR.equals(KMRinvertedList.get(i).endKMR) == false; + return (KMRinvertedList.get(i-1).beginKMR.equals(KMRinvertedList.get(i).beginKMR) == false) || + (KMRinvertedList.get(i-1).endKMR.equals(KMRinvertedList.get(i).endKMR) == false); } /** @@ -118,25 +119,22 @@ private boolean substringsAreEqual(ArrayList KMRinvertedList, int * @return list of KMRsWithIndex which indexes are nearly inverted KMR array */ private ArrayList getKMRinvertedList(ArrayList KMR, int radius, int length) { - ArrayList KMRinvertedList = new ArrayList(); - - for(int i=0; i KMRinvertedList = new ArrayList(); + for (int i=0; i() { - @Override - public int compare(KMRsWithIndex A, KMRsWithIndex B) { - if (A.beginKMR.equals(B.beginKMR) == false) { - return A.beginKMR.compareTo(B.beginKMR); - } - if (A.endKMR.equals(B.endKMR) == false) { - return A.endKMR.compareTo(B.endKMR); + Collections.sort(KMRinvertedList, + new Comparator() { + @Override + public int compare(KMRsWithIndex A, KMRsWithIndex B) { + if (A.beginKMR.equals(B.beginKMR) == false) + return A.beginKMR.compareTo(B.beginKMR); + if (A.endKMR.equals(B.endKMR) == false) + return A.endKMR.compareTo(B.endKMR); + return A.index.compareTo(B.index); } - return A.index.compareTo(B.index); } - }); - + ); return KMRinvertedList; } @@ -147,23 +145,21 @@ public int compare(KMRsWithIndex A, KMRsWithIndex B) { * @return pseudo KMR array for radius=1 */ private ArrayList getBasicKMR(int length) { - ArrayList result = new ArrayList(length*2); - char[] characters = string.toCharArray(); - for(int i=0; i result = new ArrayList(length*2); + final char[] characters = string.toCharArray(); + for (int i=0; i suffixSet = suffixTree.getSuffixes(); ArrayList suffixArray = suffixArrayBuilder.getSuffixArray(); - int length = string.length(); int i=0; for(String suffix : suffixSet){ String substring = string.substring(suffixArray.get(i++)); From e7fa8784a29df625efd098af1d06eaa04b453a23 Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Mon, 3 Jul 2017 16:32:36 -0400 Subject: [PATCH 31/88] Javadoc clean-up --- .../algorithms/data_structures/AVLTree.java | 6 +- .../algorithms/data_structures/BTree.java | 6 +- .../data_structures/BinaryHeap.java | 6 +- .../data_structures/BinarySearchTree.java | 6 +- .../data_structures/CompactSuffixTrie.java | 6 +- .../data_structures/DisjointSet.java | 14 +-- .../data_structures/FenwickTree.java | 8 +- .../algorithms/data_structures/Graph.java | 6 +- .../data_structures/HashArrayMappedTrie.java | 8 +- .../algorithms/data_structures/HashMap.java | 6 +- .../data_structures/ImplicitKeyTreap.java | 12 +- .../data_structures/IntervalTree.java | 6 +- .../algorithms/data_structures/KdTree.java | 3 +- .../algorithms/data_structures/LCPArray.java | 45 +++---- .../algorithms/data_structures/List.java | 32 +++-- .../algorithms/data_structures/Matrix.java | 6 +- .../data_structures/PatriciaTrie.java | 6 +- .../algorithms/data_structures/QuadTree.java | 6 +- .../algorithms/data_structures/Queue.java | 8 ++ .../algorithms/data_structures/RadixTrie.java | 10 +- .../data_structures/RedBlackTree.java | 6 +- .../data_structures/SegmentTree.java | 8 +- .../algorithms/data_structures/SkipList.java | 6 +- .../data_structures/SkipListMap.java | 10 +- .../algorithms/data_structures/SplayTree.java | 6 +- .../algorithms/data_structures/Stack.java | 12 +- .../data_structures/SuffixArray.java | 26 ++-- .../data_structures/SuffixTree.java | 26 ++-- .../data_structures/SuffixTrie.java | 13 +- .../algorithms/data_structures/Treap.java | 6 +- .../algorithms/data_structures/TreeMap.java | 10 +- .../algorithms/data_structures/Trie.java | 16 +-- .../algorithms/data_structures/TrieMap.java | 10 +- .../data_structures/interfaces/IHeap.java | 6 +- .../data_structures/interfaces/IList.java | 6 +- .../data_structures/interfaces/IMap.java | 6 +- .../data_structures/interfaces/IQueue.java | 6 +- .../data_structures/interfaces/ISet.java | 6 +- .../data_structures/interfaces/IStack.java | 6 +- .../interfaces/ISuffixTree.java | 6 +- .../data_structures/interfaces/ITree.java | 6 +- .../jwetherell/algorithms/graph/AStar.java | 6 +- .../algorithms/graph/BellmanFord.java | 8 +- .../graph/BreadthFirstTraversal.java | 49 +++++++- .../algorithms/graph/ConnectedComponents.java | 6 +- .../algorithms/graph/CycleDetection.java | 6 +- .../algorithms/graph/DepthFirstTraversal.java | 116 +++++++++++++++--- .../jwetherell/algorithms/graph/Dijkstra.java | 8 +- .../algorithms/graph/EdmondsKarp.java | 2 +- .../algorithms/graph/FloydWarshall.java | 8 +- .../jwetherell/algorithms/graph/Johnson.java | 8 +- .../jwetherell/algorithms/graph/Kruskal.java | 4 +- src/com/jwetherell/algorithms/graph/Prim.java | 2 +- .../algorithms/graph/PushRelabel.java | 2 +- .../algorithms/graph/TopologicalSort.java | 6 +- .../algorithms/graph/TurboMatching.java | 30 +++-- .../algorithms/mathematics/Coprimes.java | 4 +- .../mathematics/Exponentiation.java | 7 +- .../mathematics/FastFourierTransform.java | 4 +- .../mathematics/GreatestCommonDivisor.java | 4 +- .../algorithms/mathematics/Knapsack.java | 12 +- .../algorithms/mathematics/Modular.java | 2 +- .../algorithms/mathematics/Permutations.java | 2 +- .../algorithms/mathematics/Primes.java | 6 +- .../mathematics/RamerDouglasPeucker.java | 6 +- .../algorithms/numbers/Complex.java | 2 +- .../algorithms/search/BinarySearch.java | 4 +- .../search/InterpolationSearch.java | 4 +- .../algorithms/search/LinearSearch.java | 4 +- .../algorithms/search/LowerBound.java | 15 +-- .../algorithms/search/QuickSelect.java | 4 +- .../algorithms/search/UpperBound.java | 12 +- .../sequence/ArithmeticProgression.java | 4 +- .../sequence/FibonacciSequence.java | 3 +- .../LargestSumContiguousSubarray.java | 2 +- .../sequence/LongestCommonSubsequence.java | 2 +- .../LongestIncreasingSubsequence.java | 2 +- .../LongestPalindromicSubsequence.java | 25 ++-- .../sequence/SubsequenceCounter.java | 2 +- .../algorithms/sorts/AmericanFlagSort.java | 21 ++-- .../algorithms/sorts/BubbleSort.java | 20 +-- .../algorithms/sorts/CountingSort.java | 21 ++-- .../jwetherell/algorithms/sorts/HeapSort.java | 20 +-- .../algorithms/sorts/InsertionSort.java | 20 +-- .../algorithms/sorts/MergeSort.java | 20 +-- .../algorithms/sorts/QuickSort.java | 20 +-- .../algorithms/sorts/RadixSort.java | 21 ++-- .../algorithms/sorts/ShellSort.java | 22 ++-- .../algorithms/strings/KnuthMorrisPratt.java | 9 +- .../algorithms/strings/Manacher.java | 6 +- .../algorithms/strings/Rotation.java | 19 +-- .../algorithms/strings/StringFunctions.java | 2 +- .../data_structures/test/LCPArrayTest.java | 8 +- .../data_structures/test/common/HeapTest.java | 22 ---- .../test/common/IteratorTest.java | 10 -- .../test/common/JavaCollectionTest.java | 16 --- .../test/common/JavaMapTest.java | 17 --- .../test/common/ListIteratorTest.java | 13 -- .../data_structures/test/common/ListTest.java | 14 --- .../data_structures/test/common/MapTest.java | 16 --- .../test/common/QueueTest.java | 18 --- .../data_structures/test/common/SetTest.java | 14 --- .../test/common/StackTest.java | 15 --- .../data_structures/test/common/TreeTest.java | 16 --- .../graph/test/BreadthFirstTraversalTest.java | 36 +++++- .../graph/test/DepthFirstTraversalTest.java | 89 ++++++++++++++ 106 files changed, 731 insertions(+), 596 deletions(-) create mode 100644 test/com/jwetherell/algorithms/graph/test/DepthFirstTraversalTest.java diff --git a/src/com/jwetherell/algorithms/data_structures/AVLTree.java b/src/com/jwetherell/algorithms/data_structures/AVLTree.java index b5df686a..f3b74e3e 100644 --- a/src/com/jwetherell/algorithms/data_structures/AVLTree.java +++ b/src/com/jwetherell/algorithms/data_structures/AVLTree.java @@ -12,9 +12,9 @@ * trees are more rigidly balanced, they are faster than red-black trees for * lookup intensive applications. However, red-black trees are faster for * insertion and removal. - * - * http://en.wikipedia.org/wiki/AVL_tree - * + *

+ * @see AVL Tree (Wikipedia) + *
* @author Justin Wetherell */ public class AVLTree> extends BinarySearchTree { diff --git a/src/com/jwetherell/algorithms/data_structures/BTree.java b/src/com/jwetherell/algorithms/data_structures/BTree.java index 088f9f37..d15d398c 100644 --- a/src/com/jwetherell/algorithms/data_structures/BTree.java +++ b/src/com/jwetherell/algorithms/data_structures/BTree.java @@ -14,9 +14,9 @@ * two children. Unlike self-balancing binary search trees, the B-tree is * optimized for systems that read and write large blocks of data. It is * commonly used in databases and file-systems. - * - * http://en.wikipedia.org/wiki/B-tree - * + *

+ * @see B-Tree (Wikipedia) + *
* @author Justin Wetherell */ @SuppressWarnings("unchecked") diff --git a/src/com/jwetherell/algorithms/data_structures/BinaryHeap.java b/src/com/jwetherell/algorithms/data_structures/BinaryHeap.java index dd1cf53a..61f38a16 100644 --- a/src/com/jwetherell/algorithms/data_structures/BinaryHeap.java +++ b/src/com/jwetherell/algorithms/data_structures/BinaryHeap.java @@ -16,9 +16,9 @@ * the tree is not complete, the nodes of that level are filled from left to * right. 2) The heap property: each node is right than or equal to each of its * children according to a comparison predicate defined for the data structure. - * - * http://en.wikipedia.org/wiki/Binary_heap - * + *

+ * @see Binary Heap (Wikipedia) + *
* @author Justin Wetherell */ @SuppressWarnings("unchecked") diff --git a/src/com/jwetherell/algorithms/data_structures/BinarySearchTree.java b/src/com/jwetherell/algorithms/data_structures/BinarySearchTree.java index 96089b8f..d2b832a5 100644 --- a/src/com/jwetherell/algorithms/data_structures/BinarySearchTree.java +++ b/src/com/jwetherell/algorithms/data_structures/BinarySearchTree.java @@ -19,9 +19,9 @@ * keys less than the node's key. 2) The right subtree of a node contains only * nodes with keys greater than the node's key. 3) Both the left and right * subtrees must also be binary search trees. - * - * http://en.wikipedia.org/wiki/Binary_search_tree - * + *

+ * @see Binary Search Tree (Wikipedia) + *
* @author Justin Wetherell */ @SuppressWarnings("unchecked") diff --git a/src/com/jwetherell/algorithms/data_structures/CompactSuffixTrie.java b/src/com/jwetherell/algorithms/data_structures/CompactSuffixTrie.java index c88b6bcb..bc64b598 100644 --- a/src/com/jwetherell/algorithms/data_structures/CompactSuffixTrie.java +++ b/src/com/jwetherell/algorithms/data_structures/CompactSuffixTrie.java @@ -8,9 +8,9 @@ * string in a way that allows for a particularly fast implementation of many * important string operations. This implementation is based upon a patricia * trie which IS a compact trie. - * - * http://en.wikipedia.org/wiki/Suffix_trie - * + *

+ * @see Suffix Trie (Wikipedia) + *
* @author Justin Wetherell */ @SuppressWarnings("unchecked") diff --git a/src/com/jwetherell/algorithms/data_structures/DisjointSet.java b/src/com/jwetherell/algorithms/data_structures/DisjointSet.java index 6b4c1dbb..c7c02a08 100644 --- a/src/com/jwetherell/algorithms/data_structures/DisjointSet.java +++ b/src/com/jwetherell/algorithms/data_structures/DisjointSet.java @@ -3,14 +3,14 @@ /** * In computer science, a disjoint-set data structure, also called a union–find data structure or merge–find set, is a data structure that keeps track of a set of * elements partitioned into a number of disjoint (non-overlapping) subsets. - * - * It supports two useful operations: + *

+ * It supports two useful operations:
* Find: Determine which subset a particular element is in. Find typically returns an item from this set that serves as its "representative"; by comparing the - * result of two Find operations, one can determine whether two elements are in the same subset. - * Union: Join two subsets into a single subset. - * - * http://en.wikipedia.org/wiki/Disjoint-set_data_structure - * + * result of two Find operations, one can determine whether two elements are in the same subset.
+ * Union: Join two subsets into a single subset.
+ *

+ * @see Disjoint Set (Wikipedia) + *
* @author Justin Wetherell */ @SuppressWarnings("unchecked") diff --git a/src/com/jwetherell/algorithms/data_structures/FenwickTree.java b/src/com/jwetherell/algorithms/data_structures/FenwickTree.java index cf936211..60634d40 100644 --- a/src/com/jwetherell/algorithms/data_structures/FenwickTree.java +++ b/src/com/jwetherell/algorithms/data_structures/FenwickTree.java @@ -10,13 +10,13 @@ * for calculation and manipulation of the prefix sums of a table of values. Fenwick trees * primarily solve the problem of balancing prefix sum calculation efficiency with element * modification efficiency. - * - * http://en.wikipedia.org/wiki/Fenwick_tree - * + *

* This class is meant to be somewhat generic, all you'd have to do is extend * the Data abstract class to store your custom data. I've included a range sum * implementations. - * + *

+ * @see Fenwick Tree (Wikipedia) + *
* @author Justin Wetherell */ @SuppressWarnings("unchecked") diff --git a/src/com/jwetherell/algorithms/data_structures/Graph.java b/src/com/jwetherell/algorithms/data_structures/Graph.java index d52f7baf..c28bbc6e 100644 --- a/src/com/jwetherell/algorithms/data_structures/Graph.java +++ b/src/com/jwetherell/algorithms/data_structures/Graph.java @@ -10,9 +10,9 @@ * Graph. Could be directed or undirected depending on the TYPE enum. A graph is * an abstract representation of a set of objects where some pairs of the * objects are connected by links. - * - * http://en.wikipedia.org/wiki/Graph_(mathematics) - * + *

+ * @see Graph (Wikipedia) + *
* @author Justin Wetherell */ @SuppressWarnings("unchecked") diff --git a/src/com/jwetherell/algorithms/data_structures/HashArrayMappedTrie.java b/src/com/jwetherell/algorithms/data_structures/HashArrayMappedTrie.java index 3f177faa..b33d361b 100644 --- a/src/com/jwetherell/algorithms/data_structures/HashArrayMappedTrie.java +++ b/src/com/jwetherell/algorithms/data_structures/HashArrayMappedTrie.java @@ -10,12 +10,12 @@ * A hash array mapped trie (HAMT) is an implementation of an associative * array that combines the characteristics of a hash table and an array mapped * trie. It is a refined version of the more general notion of a hash tree. - * + *

* This implementation is 32-bit and steps in 5-bit intervals, maximum tree * height of 7. - * - * http://en.wikipedia.org/wiki/Hash_array_mapped_trie - * + *

+ * @see Hash Array Mapped Trie (Wikipedia) + *
* @author Justin Wetherell */ @SuppressWarnings("unchecked") diff --git a/src/com/jwetherell/algorithms/data_structures/HashMap.java b/src/com/jwetherell/algorithms/data_structures/HashMap.java index 2245eb34..76c669de 100644 --- a/src/com/jwetherell/algorithms/data_structures/HashMap.java +++ b/src/com/jwetherell/algorithms/data_structures/HashMap.java @@ -9,9 +9,9 @@ * Hash Map using either chaining or probing. hash map is a data structure that * uses a hash function to map identifying values, known as keys, to their * associated values. - * - * http://en.wikipedia.org/wiki/Hash_table - * + *

+ * @see Hash Map/Table (Wikipedia) + *
* @author Justin Wetherell */ @SuppressWarnings("unchecked") diff --git a/src/com/jwetherell/algorithms/data_structures/ImplicitKeyTreap.java b/src/com/jwetherell/algorithms/data_structures/ImplicitKeyTreap.java index d709b44b..bc98df10 100644 --- a/src/com/jwetherell/algorithms/data_structures/ImplicitKeyTreap.java +++ b/src/com/jwetherell/algorithms/data_structures/ImplicitKeyTreap.java @@ -9,18 +9,18 @@ /** * A Treap is a self-balancing binary search tree that uses randomization to maintain * a low height. In this version, it is used emulate the operations of an array and linked list. - * + *

* Time Complexity: Assuming the join/merge functions have constant complexity. * add(value), add(index,value), remove(index), set(index,value), get(index) all have O(log N). * remove(value), get(value), contains(value) all have O(N). - * + *

* Space Complexity: O(N) - * + *

* Note: This implementation is 0-based, meaning that all * indices from 0 to size() - 1, inclusive, are accessible. - * - * http://en.wikipedia.org/wiki/Treap - * + *

+ * @see Treap (Wikipedia) + *
* @author Justin Wetherell */ @SuppressWarnings("unchecked") diff --git a/src/com/jwetherell/algorithms/data_structures/IntervalTree.java b/src/com/jwetherell/algorithms/data_structures/IntervalTree.java index 9a341efa..a04113ba 100644 --- a/src/com/jwetherell/algorithms/data_structures/IntervalTree.java +++ b/src/com/jwetherell/algorithms/data_structures/IntervalTree.java @@ -12,9 +12,9 @@ * An interval tree is an ordered tree data structure to hold intervals. * Specifically, it allows one to efficiently find all intervals that overlap * with any given interval or point. - * - * http://en.wikipedia.org/wiki/Interval_tree - * + *

+ * @see Interval Tree (Wikipedia) + *
* @author Justin Wetherell */ public class IntervalTree { diff --git a/src/com/jwetherell/algorithms/data_structures/KdTree.java b/src/com/jwetherell/algorithms/data_structures/KdTree.java index 9fecb819..b7558302 100644 --- a/src/com/jwetherell/algorithms/data_structures/KdTree.java +++ b/src/com/jwetherell/algorithms/data_structures/KdTree.java @@ -21,9 +21,10 @@ * useful data structure for several applications, such as searches involving a * multidimensional search key (e.g. range searches and nearest neighbor * searches). k-d trees are a special case of binary space partitioning trees. + *

+ * @see K-D Tree (Wikipedia) *
* @author Justin Wetherell - * @see K-d_tree (Wikipedia) */ public class KdTree implements Iterable { diff --git a/src/com/jwetherell/algorithms/data_structures/LCPArray.java b/src/com/jwetherell/algorithms/data_structures/LCPArray.java index 88d299c8..9dd1632d 100644 --- a/src/com/jwetherell/algorithms/data_structures/LCPArray.java +++ b/src/com/jwetherell/algorithms/data_structures/LCPArray.java @@ -7,32 +7,33 @@ * data structure to the suffix array. It stores the lengths of the longest common * prefixes (LCPs) between all pairs of consecutive suffixes in a sorted suffix array. *

- * https://en.wikipedia.org/wiki/LCP_array + * @see LCP Array (Wikipedia) *
* @author Jakub Szarawarski * @author Justin Wetherell */ -public class LCPArray { +public class LCPArray { private static final char DEFAULT_END_SEQ_CHAR = '$'; - private char END_SEQ_CHAR; - private SuffixArray suffixArrayBuilder; - private ArrayList LCP; + private final char endSeqChar; - public LCPArray(CharSequence sequence){ + private SuffixArray suffixArray; + private ArrayList lcp; + + public LCPArray(C sequence){ this(sequence, DEFAULT_END_SEQ_CHAR); } - public LCPArray(CharSequence sequence, char endChar) { - END_SEQ_CHAR = endChar; - suffixArrayBuilder = new SuffixArray(sequence, END_SEQ_CHAR); + public LCPArray(C sequence, char endChar) { + endSeqChar = endChar; + suffixArray = new SuffixArray(sequence, endSeqChar); } public ArrayList getLCPArray() { - if (LCP == null) + if (lcp == null) LCPAlgorithm(); - return LCP; + return lcp; } private void LCPAlgorithm() { @@ -41,20 +42,20 @@ private void LCPAlgorithm() { } private ArrayList getLCPR() { - final ArrayList KMRArray = suffixArrayBuilder.getKMRarray(); - final ArrayList suffixArray = suffixArrayBuilder.getSuffixArray(); - final String string = suffixArrayBuilder.getString(); - final int length = KMRArray.size(); + final ArrayList KMRArrayList = suffixArray.getKMRarray(); + final ArrayList suffixArrayList = suffixArray.getSuffixArray(); + final String string = suffixArray.getString(); + final int length = KMRArrayList.size(); final ArrayList LCPR = new ArrayList(); // helper array, LCP[i] = LCPR[suffixArray[i]] int startingValue = 0; for (int i=0; i getLCPR() { } private void getLCPfromLCPR(ArrayList LCPR) { - final ArrayList suffixArray = suffixArrayBuilder.getSuffixArray(); - final int length = suffixArray.size(); + final ArrayList suffixArrayList = suffixArray.getSuffixArray(); + final int length = suffixArrayList.size(); - LCP = new ArrayList(); - LCP.add(null); //no value for LCP[0] + lcp = new ArrayList(); + lcp.add(null); //no value for LCP[0] for (int i=1; i + * @see Sequence (Wikipedia) + *
+ * @author Justin Wetherell + */ @SuppressWarnings("unchecked") public abstract class List implements IList { @@ -11,9 +19,9 @@ public abstract class List implements IList { * A dynamic array, growable array, resizable array, dynamic table, or array * list is a random access, variable-size list data structure that allows * elements to be added or removed. - * - * http://en.wikipedia.org/wiki/Dynamic_array - * + *

+ * @see Dynamic Array (Wikipedia) + *
* @author Justin Wetherell */ public static class ArrayList extends List { @@ -280,9 +288,9 @@ public T set(int index, T value) { /** * Linked List (Singly link). A linked list is a data structure consisting * of a group of nodes which together represent a sequence. - * - * http://en.wikipedia.org/wiki/Linked_list - * + *

+ * @see Linked List (Wikipedia) + *
* @author Justin Wetherell */ public static class SinglyLinkedList extends List { @@ -477,9 +485,9 @@ public String toString() { /** * Linked List (singly link). A linked list is a data structure consisting * of a group of nodes which together represent a sequence. - * - * http://en.wikipedia.org/wiki/Linked_list - * + *

+ * @see Linked List (Wikipedia) + *
* @author Justin Wetherell */ public static class JavaCompatibleSinglyLinkedList extends java.util.AbstractSequentialList { @@ -688,9 +696,9 @@ public T previous() { /** * Linked List (doubly link). A linked list is a data structure consisting * of a group of nodes which together represent a sequence. - * - * http://en.wikipedia.org/wiki/Linked_list - * + *

+ * @see Linked List (Wikipedia) + *
* @author Justin Wetherell */ public static class DoublyLinkedList extends List { diff --git a/src/com/jwetherell/algorithms/data_structures/Matrix.java b/src/com/jwetherell/algorithms/data_structures/Matrix.java index 717b757c..a835210b 100644 --- a/src/com/jwetherell/algorithms/data_structures/Matrix.java +++ b/src/com/jwetherell/algorithms/data_structures/Matrix.java @@ -7,9 +7,9 @@ /** * Matrx. This Matrix implementation is designed to be more efficient * in cache. A matrix is a rectangular array of numbers, symbols, or expressions. - * - * http://en.wikipedia.org/wiki/Matrix_(mathematics) - * + *

+ * @see Matrix (Wikipedia) + *
* @author Justin Wetherell */ @SuppressWarnings("unchecked") diff --git a/src/com/jwetherell/algorithms/data_structures/PatriciaTrie.java b/src/com/jwetherell/algorithms/data_structures/PatriciaTrie.java index 4354d037..b3bce4bc 100644 --- a/src/com/jwetherell/algorithms/data_structures/PatriciaTrie.java +++ b/src/com/jwetherell/algorithms/data_structures/PatriciaTrie.java @@ -9,9 +9,9 @@ * non-terminating (black) node with only one child is merged with its child. * The result is that every internal non-terminating (black) node has at least * two children. Each terminating node (white) represents the end of a string. - * - * http://en.wikipedia.org/wiki/Radix_tree - * + *

+ * @see Radix Tree / Patricia Trie (Wikipedia) + *
* @author Justin Wetherell */ @SuppressWarnings("unchecked") diff --git a/src/com/jwetherell/algorithms/data_structures/QuadTree.java b/src/com/jwetherell/algorithms/data_structures/QuadTree.java index 69f664d2..0535a245 100644 --- a/src/com/jwetherell/algorithms/data_structures/QuadTree.java +++ b/src/com/jwetherell/algorithms/data_structures/QuadTree.java @@ -11,9 +11,9 @@ * A quadtree is a tree data structure in which each internal node has exactly four children. Quadtrees * are most often used to partition a two dimensional space by recursively subdividing it into four * quadrants or regions. The regions may be square or rectangular, or may have arbitrary shapes. - * - * http://en.wikipedia.org/wiki/Quadtree - * + *

+ * @see QuadTree (Wikipedia) + *
* @author Justin Wetherell */ @SuppressWarnings("unchecked") diff --git a/src/com/jwetherell/algorithms/data_structures/Queue.java b/src/com/jwetherell/algorithms/data_structures/Queue.java index 7a05f86f..1a078f71 100644 --- a/src/com/jwetherell/algorithms/data_structures/Queue.java +++ b/src/com/jwetherell/algorithms/data_structures/Queue.java @@ -2,6 +2,14 @@ import com.jwetherell.algorithms.data_structures.interfaces.IQueue; +/** + * In computer science, a queue is a particular kind of abstract data type or collection in which the entities in the collection are kept in order and the principal (or only) operations + * on the collection are the addition of entities to the rear terminal position, known as enqueue, and removal of entities from the front terminal position, known as dequeue. + *

+ * @see Queue (Wikipedia) + *
+ * @author Justin Wetherell + */ @SuppressWarnings("unchecked") public interface Queue extends IQueue { diff --git a/src/com/jwetherell/algorithms/data_structures/RadixTrie.java b/src/com/jwetherell/algorithms/data_structures/RadixTrie.java index 1188ca74..012f0d01 100644 --- a/src/com/jwetherell/algorithms/data_structures/RadixTrie.java +++ b/src/com/jwetherell/algorithms/data_structures/RadixTrie.java @@ -10,13 +10,13 @@ * This makes them much more efficient for small sets (especially if the strings * are long) and for sets of strings that share long prefixes. This particular * radix tree is used to represent an associative array. - * + *

* This implementation is a composition of a PatriciaTrie as the backing * structure. - * - * http://en.wikipedia.org/wiki/Radix_tree - * http://en.wikipedia.org/wiki/Associative_array - * + *

+ * @see Radix Tree / Patricia Trie (Wikipedia) + * @see Associative Array (Wikipedia) + *
* @author Justin Wetherell */ @SuppressWarnings("unchecked") diff --git a/src/com/jwetherell/algorithms/data_structures/RedBlackTree.java b/src/com/jwetherell/algorithms/data_structures/RedBlackTree.java index 451db6db..c3c7400c 100644 --- a/src/com/jwetherell/algorithms/data_structures/RedBlackTree.java +++ b/src/com/jwetherell/algorithms/data_structures/RedBlackTree.java @@ -14,9 +14,9 @@ * often compared with AVL trees. AVL trees are more rigidly balanced, they are * faster than red-black trees for lookup intensive applications. However, * red-black trees are faster for insertion and removal. - * - * http://en.wikipedia.org/wiki/Red%E2%80%93black_tree - * + *

+ * @see Red-Black Tree (Wikipedia) + *
* @author Justin Wetherell */ @SuppressWarnings("unchecked") diff --git a/src/com/jwetherell/algorithms/data_structures/SegmentTree.java b/src/com/jwetherell/algorithms/data_structures/SegmentTree.java index 3ae10898..9a04b8e6 100644 --- a/src/com/jwetherell/algorithms/data_structures/SegmentTree.java +++ b/src/com/jwetherell/algorithms/data_structures/SegmentTree.java @@ -18,13 +18,13 @@ * stored segments contain a given point. It is, in principle, a static * structure; that is, its content cannot be modified once the structure is * built. - * - * http://en.wikipedia.org/wiki/Segment_tree - * + *

* This class is meant to be somewhat generic, all you'd have to do is extend * the Data abstract class to store your custom data. I've also included a range * minimum, range maximum, range sum, and interval stabbing implementations. - * + *

+ * @see Segment Tree (Wikipedia) + *
* @author Justin Wetherell */ @SuppressWarnings("unchecked") diff --git a/src/com/jwetherell/algorithms/data_structures/SkipList.java b/src/com/jwetherell/algorithms/data_structures/SkipList.java index 5743fa32..29b61f70 100644 --- a/src/com/jwetherell/algorithms/data_structures/SkipList.java +++ b/src/com/jwetherell/algorithms/data_structures/SkipList.java @@ -9,9 +9,9 @@ * using a hierarchy of linked lists that connect increasingly sparse * subsequences of the items. These auxiliary lists allow item lookup with * efficiency comparable to balanced binary search trees. - * - * http://en.wikipedia.org/wiki/Skip_list - * + *

+ * @see Skip List (Wikipedia) + *
* @author Justin Wetherell */ @SuppressWarnings("unchecked") diff --git a/src/com/jwetherell/algorithms/data_structures/SkipListMap.java b/src/com/jwetherell/algorithms/data_structures/SkipListMap.java index df811c23..d7c77eb9 100644 --- a/src/com/jwetherell/algorithms/data_structures/SkipListMap.java +++ b/src/com/jwetherell/algorithms/data_structures/SkipListMap.java @@ -6,12 +6,12 @@ /** * A set used to store key->values pairs, this is an implementation of an * associative array. - * + *

* This implementation is a composition of a Skip List as the backing structure. - * - * http://en.wikipedia.org/wiki/Skip_list - * http://en.wikipedia.org/wiki/Associative_array - * + *

+ * @see Skip List (Wikipedia) + * @see Associative Array (Wikipedia) + *
* @author Justin Wetherell */ @SuppressWarnings("unchecked") diff --git a/src/com/jwetherell/algorithms/data_structures/SplayTree.java b/src/com/jwetherell/algorithms/data_structures/SplayTree.java index 90ed9c27..d6e279db 100644 --- a/src/com/jwetherell/algorithms/data_structures/SplayTree.java +++ b/src/com/jwetherell/algorithms/data_structures/SplayTree.java @@ -3,9 +3,9 @@ /** * A splay tree is a self-adjusting binary search tree (BST) with the additional * property that recently accessed elements are quick to access again. - * - * http://en.wikipedia.org/wiki/Splay_tree - * + *

+ * @see Splay Tree (Wikipedia) + *
* @author Justin Wetherell */ public class SplayTree> extends BinarySearchTree { diff --git a/src/com/jwetherell/algorithms/data_structures/Stack.java b/src/com/jwetherell/algorithms/data_structures/Stack.java index 62e0cc92..2ad749c2 100644 --- a/src/com/jwetherell/algorithms/data_structures/Stack.java +++ b/src/com/jwetherell/algorithms/data_structures/Stack.java @@ -4,12 +4,20 @@ import com.jwetherell.algorithms.data_structures.interfaces.IStack; +/** + * In computer science, a stack is an abstract data type that serves as a collection of elements, with two principal operations: push, which adds an element to the collection, and pop, which removes + * the most recently added element that was not yet removed. + *

+ * @see Stack (Wikipedia) + *
+ * @author Justin Wetherell + */ @SuppressWarnings("unchecked") public interface Stack extends IStack { /** * This stack implementation is backed by an array. - * + *

* @author Justin Wetherell */ public static class ArrayStack implements Stack { @@ -187,7 +195,7 @@ public String toString() { /** * This stack implementation is backed by a linked list. - * + *

* @author Justin Wetherell */ public static class LinkedStack implements Stack { diff --git a/src/com/jwetherell/algorithms/data_structures/SuffixArray.java b/src/com/jwetherell/algorithms/data_structures/SuffixArray.java index a7212f18..2d01ed9f 100644 --- a/src/com/jwetherell/algorithms/data_structures/SuffixArray.java +++ b/src/com/jwetherell/algorithms/data_structures/SuffixArray.java @@ -9,7 +9,7 @@ * It is a data structure used, among others, in full text indices, data compression * algorithms and within the field of bibliometrics. *

- * https://en.wikipedia.org/wiki/Suffix_array + * @see Suffix Array (Wikipedia) *

* NOTE: This implementation returns starting indexes instead of full suffixes *
@@ -21,17 +21,18 @@ public class SuffixArray { private static final StringBuilder STRING_BUILDER = new StringBuilder(); private static final char DEFAULT_END_SEQ_CHAR = '$'; - private char END_SEQ_CHAR; + private final char endSeqChar; + private String string; - private ArrayList suffixArray = null; - private ArrayList KMRarray = null; + private ArrayList suffixArray; + private ArrayList KMRarray; public SuffixArray(CharSequence sequence) { this(sequence, DEFAULT_END_SEQ_CHAR); } public SuffixArray(CharSequence sequence, char endChar) { - END_SEQ_CHAR = endChar; + endSeqChar = endChar; string = buildStringWithEndChar(sequence); } @@ -78,8 +79,9 @@ private void KMRalgorithm() { KMRarray = new ArrayList(KMR.subList(0, length)); suffixArray = new ArrayList(); - for (KMRsWithIndex kmr : KMRinvertedList) - suffixArray.add(kmr.index); + for (KMRsWithIndex kmr : KMRinvertedList) { + suffixArray.add(new Integer(kmr.index)); + } } /** @@ -93,13 +95,13 @@ private void KMRalgorithm() { private ArrayList getKMR(ArrayList KMRinvertedList, int length) { final ArrayList KMR = new ArrayList(length*2); for (int i=0; i<2*length; i++) - KMR.add(-1); + KMR.add(new Integer(-1)); int counter = 0; for (int i=0; i0 && substringsAreEqual(KMRinvertedList, i)) counter++; - KMR.set(KMRinvertedList.get(i).index, counter); + KMR.set(KMRinvertedList.get(i).index, new Integer(counter)); } return KMR; @@ -150,15 +152,15 @@ private ArrayList getBasicKMR(int length) { for (int i=0; i + * @see Suffix Tree (Wikipedia) + *
* @author Justin Wetherell */ public class SuffixTree implements ISuffixTree { private static final char DEFAULT_END_SEQ_CHAR = '$'; - private String string = null; - private char[] characters = null; + private final char endSeqChar; private Map linksMap = new HashMap(); private Map> edgeMap = new TreeMap>(); @@ -34,7 +33,8 @@ public class SuffixTree implements ISuffixTree { private int firstCharIndex = 0; private int lastCharIndex = -1; - private char END_SEQ_CHAR = DEFAULT_END_SEQ_CHAR; + private String string; + private char[] characters; /** * Create suffix tree with sequence and default end sequence. @@ -55,10 +55,10 @@ public SuffixTree(C seq) { * which defines the end of a sequence. */ public SuffixTree(C seq, char endSeq) { - END_SEQ_CHAR = endSeq; + endSeqChar = endSeq; StringBuilder builder = new StringBuilder(seq); - if (builder.indexOf(String.valueOf(END_SEQ_CHAR)) < 0) - builder.append(END_SEQ_CHAR); + if (builder.indexOf(String.valueOf(endSeqChar)) < 0) + builder.append(endSeqChar); string = builder.toString(); int length = string.length(); characters = new char[length]; @@ -124,14 +124,14 @@ private Set getSuffixes(int start) { String s = (string.substring(e.firstCharIndex, e.lastCharIndex + 1)); Link n = linksMap.get(e.endNode); if (n == null) { - int index = s.indexOf(END_SEQ_CHAR); + int index = s.indexOf(endSeqChar); if (index >= 0) s = s.substring(0, index); set.add(s); } else { Set set2 = getSuffixes(e.endNode); for (String s2 : set2) { - int index = s2.indexOf(END_SEQ_CHAR); + int index = s2.indexOf(endSeqChar); if (index >= 0) s2 = s2.substring(0, index); set.add(s + s2); @@ -297,7 +297,7 @@ private int[] searchEdges(char[] query) { public String toString() { StringBuilder builder = new StringBuilder(); builder.append("String = ").append(this.string).append("\n"); - builder.append("End of word character = ").append(END_SEQ_CHAR).append("\n"); + builder.append("End of word character = ").append(endSeqChar).append("\n"); builder.append(TreePrinter.getString(this)); return builder.toString(); } @@ -514,7 +514,7 @@ private static String getString(SuffixTree tree, Edg if (e != null) { value = e.endNode; String string = tree.string.substring(e.firstCharIndex, e.lastCharIndex + 1); - int index = string.indexOf(tree.END_SEQ_CHAR); + int index = string.indexOf(tree.endSeqChar); if (index >= 0) string = string.substring(0, index + 1); builder.append(prefix + (isTail ? "└── " : "├── ") + "(" + value + ") " + string + "\n"); diff --git a/src/com/jwetherell/algorithms/data_structures/SuffixTrie.java b/src/com/jwetherell/algorithms/data_structures/SuffixTrie.java index 774f53c8..e82af621 100644 --- a/src/com/jwetherell/algorithms/data_structures/SuffixTrie.java +++ b/src/com/jwetherell/algorithms/data_structures/SuffixTrie.java @@ -9,17 +9,18 @@ /** * A suffix trie is a data structure that presents the suffixes of a given * string in a way that allows for a particularly fast implementation of many - * important string operations. This implementation is based upon a Trie which - * is NOT a compact trie. - * - * http://en.wikipedia.org/wiki/Suffix_trie - * + * important string operations. + *

+ * This implementation is based upon a Trie which is NOT a compact trie. + *

+ * @see Suffix Trie (Wikipedia) + *
* @author Justin Wetherell */ @SuppressWarnings("unchecked") public class SuffixTrie implements ISuffixTree { - private Trie tree = null; + private Trie tree; /** * Create a suffix trie from sequence diff --git a/src/com/jwetherell/algorithms/data_structures/Treap.java b/src/com/jwetherell/algorithms/data_structures/Treap.java index 99f87e11..79792f37 100644 --- a/src/com/jwetherell/algorithms/data_structures/Treap.java +++ b/src/com/jwetherell/algorithms/data_structures/Treap.java @@ -12,9 +12,9 @@ * particular, with high probability its height is proportional to the logarithm * of the number of values, so that each search, insertion, or deletion * operation takes logarithmic time to perform. - * - * http://en.wikipedia.org/wiki/Treap - * + *

+ * @see Treap (Wikipedia) + *
* @author Justin Wetherell */ public class Treap> extends BinarySearchTree { diff --git a/src/com/jwetherell/algorithms/data_structures/TreeMap.java b/src/com/jwetherell/algorithms/data_structures/TreeMap.java index fe58d88a..728d7750 100644 --- a/src/com/jwetherell/algorithms/data_structures/TreeMap.java +++ b/src/com/jwetherell/algorithms/data_structures/TreeMap.java @@ -10,12 +10,12 @@ /** * An tree used to store key->values pairs, this is an implementation of an * associative array. - * + *

* This implementation is a composition of a AVLTree as the backing structure. - * - * http://en.wikipedia.org/wiki/AVL_tree - * http://en.wikipedia.org/wiki/Associative_array - * + *

+ * @see AVL Tree (Wikipedia) + * @see Associative Array (Wikipedia) + *
* @author Justin Wetherell */ @SuppressWarnings("unchecked") diff --git a/src/com/jwetherell/algorithms/data_structures/Trie.java b/src/com/jwetherell/algorithms/data_structures/Trie.java index 2c900c95..7ff1bfd2 100644 --- a/src/com/jwetherell/algorithms/data_structures/Trie.java +++ b/src/com/jwetherell/algorithms/data_structures/Trie.java @@ -7,20 +7,20 @@ /** * A trie, or prefix tree, is an ordered tree data structure that is used to * store an associative array where the keys are usually strings. - * - * == This is NOT a compact Trie. == - * - * http://en.wikipedia.org/wiki/Trie - * + *

+ * NOTE: This is NOT a compact Trie + *

+ * @see Trie (Wikipedia) + *
* @author Justin Wetherell */ @SuppressWarnings("unchecked") public class Trie implements ITree { - private int size = 0; + protected INodeCreator creator; + protected Node root; - protected INodeCreator creator = null; - protected Node root = null; + private int size = 0; public Trie() { this.creator = new INodeCreator() { diff --git a/src/com/jwetherell/algorithms/data_structures/TrieMap.java b/src/com/jwetherell/algorithms/data_structures/TrieMap.java index 86db4d73..06037c7d 100644 --- a/src/com/jwetherell/algorithms/data_structures/TrieMap.java +++ b/src/com/jwetherell/algorithms/data_structures/TrieMap.java @@ -6,12 +6,12 @@ /** * A trie used to store key->values pairs, this is an implementation of an * associative array. - * + *

* This implementation is a composition using a Trie as the backing structure. - * - * http://en.wikipedia.org/wiki/Trie - * http://en.wikipedia.org/wiki/Associative_array - * + *

+ * @see Trie (Wikipedia) + * @see Associative Array (Wikipedia) + *
* @author Justin Wetherell */ @SuppressWarnings("unchecked") diff --git a/src/com/jwetherell/algorithms/data_structures/interfaces/IHeap.java b/src/com/jwetherell/algorithms/data_structures/interfaces/IHeap.java index ca70da88..14e9ec8f 100644 --- a/src/com/jwetherell/algorithms/data_structures/interfaces/IHeap.java +++ b/src/com/jwetherell/algorithms/data_structures/interfaces/IHeap.java @@ -7,9 +7,9 @@ * the keys of parent nodes are always greater than or equal to those of the children * and the highest key is in the root node (this kind of heap is called max heap) or * the keys of parent nodes are less than or equal to those of the children (min heap). - * - * http://en.wikipedia.org/wiki/Heap - * + *

+ * @see Heap (Wikipedia) + *
* @author Justin Wetherell */ public interface IHeap { diff --git a/src/com/jwetherell/algorithms/data_structures/interfaces/IList.java b/src/com/jwetherell/algorithms/data_structures/interfaces/IList.java index 345b421f..1cc75929 100644 --- a/src/com/jwetherell/algorithms/data_structures/interfaces/IList.java +++ b/src/com/jwetherell/algorithms/data_structures/interfaces/IList.java @@ -3,9 +3,9 @@ /** * A list or sequence is an abstract data type that implements an ordered * collection of values, where the same value may occur more than once. - * - * http://en.wikipedia.org/wiki/List_(computing) - * + *

+ * @see List (Wikipedia) + *
* @author Justin Wetherell */ public interface IList { diff --git a/src/com/jwetherell/algorithms/data_structures/interfaces/IMap.java b/src/com/jwetherell/algorithms/data_structures/interfaces/IMap.java index 131d78aa..c47df1db 100644 --- a/src/com/jwetherell/algorithms/data_structures/interfaces/IMap.java +++ b/src/com/jwetherell/algorithms/data_structures/interfaces/IMap.java @@ -4,9 +4,9 @@ * In computer science, an associative array, map, or dictionary is an abstract * data type composed of a collection of (key, value) pairs, such that each possible * key appears at most once in the collection. - * - * http://en.wikipedia.org/wiki/Associative_array - * + *

+ * @see Associative Array (Wikipedia) + *
* @author Justin Wetherell */ public interface IMap { diff --git a/src/com/jwetherell/algorithms/data_structures/interfaces/IQueue.java b/src/com/jwetherell/algorithms/data_structures/interfaces/IQueue.java index 3cf40dd8..a5c9af8c 100644 --- a/src/com/jwetherell/algorithms/data_structures/interfaces/IQueue.java +++ b/src/com/jwetherell/algorithms/data_structures/interfaces/IQueue.java @@ -8,9 +8,9 @@ * This makes the queue a First-In-First-Out (FIFO) data structure. In a FIFO * data structure, the first element added to the queue will be the first one to * be removed. - * - * http://en.wikipedia.org/wiki/Queue_(abstract_data_type) - * + *

+ * @see Queue (Wikipedia) + *
* @author Justin Wetherell */ public interface IQueue { diff --git a/src/com/jwetherell/algorithms/data_structures/interfaces/ISet.java b/src/com/jwetherell/algorithms/data_structures/interfaces/ISet.java index 6929c83a..3e565190 100644 --- a/src/com/jwetherell/algorithms/data_structures/interfaces/ISet.java +++ b/src/com/jwetherell/algorithms/data_structures/interfaces/ISet.java @@ -5,9 +5,9 @@ * any particular order, and no repeated values. It is a computer implementation of the mathematical * concept of a finite set. Unlike most other collection types, rather than retrieving a specific * element from a set, one typically tests a value for membership in a set. - * - * http://en.wikipedia.org/wiki/Set_(abstract_data_type) - * + *

+ * @see Set (Wikipedia) + *
* @author Justin Wetherell */ public interface ISet { diff --git a/src/com/jwetherell/algorithms/data_structures/interfaces/IStack.java b/src/com/jwetherell/algorithms/data_structures/interfaces/IStack.java index 0a00f781..cf2d41b5 100644 --- a/src/com/jwetherell/algorithms/data_structures/interfaces/IStack.java +++ b/src/com/jwetherell/algorithms/data_structures/interfaces/IStack.java @@ -8,9 +8,9 @@ * if it is empty. If the stack is full and does not contain enough space to * accept the given item, the stack is then considered to be in an overflow * state. The pop operation removes an item from the top of the stack. - * - * http://en.wikipedia.org/wiki/Stack_(abstract_data_type) - * + *

+ * @see Stack (Wikipedia) + *
* @author Justin Wetherell */ public interface IStack { diff --git a/src/com/jwetherell/algorithms/data_structures/interfaces/ISuffixTree.java b/src/com/jwetherell/algorithms/data_structures/interfaces/ISuffixTree.java index 6aec9aa3..64fd913c 100644 --- a/src/com/jwetherell/algorithms/data_structures/interfaces/ISuffixTree.java +++ b/src/com/jwetherell/algorithms/data_structures/interfaces/ISuffixTree.java @@ -6,9 +6,9 @@ * In computer science, a suffix tree (also called PAT tree or, in an earlier form, position tree) is a compressed trie * containing all the suffixes of the given text as their keys and positions in the text as their values. Suffix trees * allow particularly fast implementations of many important string operations. - * - * http://en.wikipedia.org/wiki/Suffix_tree - * + *

+ * @see Suffix Tree (Wikipedia) + *
* @author Justin Wetherell */ public interface ISuffixTree { diff --git a/src/com/jwetherell/algorithms/data_structures/interfaces/ITree.java b/src/com/jwetherell/algorithms/data_structures/interfaces/ITree.java index a1b63cd7..1e48299b 100644 --- a/src/com/jwetherell/algorithms/data_structures/interfaces/ITree.java +++ b/src/com/jwetherell/algorithms/data_structures/interfaces/ITree.java @@ -5,9 +5,9 @@ * where each node is a data structure consisting of a value, together with a list of nodes (the "children"), * with the constraints that no node is duplicated. A tree can be defined abstractly as a whole (globally) * as an ordered tree, with a value assigned to each node. - * - * http://en.wikipedia.org/wiki/Tree_(data_structure) - * + *

+ * @see Tree (Wikipedia) + *
* @author Justin Wetherell */ public interface ITree { diff --git a/src/com/jwetherell/algorithms/graph/AStar.java b/src/com/jwetherell/algorithms/graph/AStar.java index 3a957dbc..c8e3c751 100644 --- a/src/com/jwetherell/algorithms/graph/AStar.java +++ b/src/com/jwetherell/algorithms/graph/AStar.java @@ -16,9 +16,9 @@ /** * In computer science, A* is a computer algorithm that is widely used in path finding and graph traversal, the process * of plotting an efficiently traversable path between multiple points, called nodes. - * - * http://en.wikipedia.org/wiki/A*_search_algorithm - * + *

+ * @see A* Algorithm (Wikipedia) + *
* @author Justin Wetherell */ public class AStar> { diff --git a/src/com/jwetherell/algorithms/graph/BellmanFord.java b/src/com/jwetherell/algorithms/graph/BellmanFord.java index 320313bf..a7e0b56c 100644 --- a/src/com/jwetherell/algorithms/graph/BellmanFord.java +++ b/src/com/jwetherell/algorithms/graph/BellmanFord.java @@ -11,11 +11,11 @@ * Bellman-Ford's shortest path. Works on both negative and positive weighted * edges. Also detects negative weight cycles. Returns a tuple of total cost of * shortest path and the path. - * + *

* Worst case: O(|V| |E|) - * - * https://en.wikipedia.org/wiki/Bellman%E2%80%93Ford_algorithm - * + *

+ * @see Bellman Ford (Wikipedia) + *
* @author Justin Wetherell */ public class BellmanFord { diff --git a/src/com/jwetherell/algorithms/graph/BreadthFirstTraversal.java b/src/com/jwetherell/algorithms/graph/BreadthFirstTraversal.java index c634d4d7..d6e1b8e4 100644 --- a/src/com/jwetherell/algorithms/graph/BreadthFirstTraversal.java +++ b/src/com/jwetherell/algorithms/graph/BreadthFirstTraversal.java @@ -11,7 +11,14 @@ import com.jwetherell.algorithms.data_structures.Graph.Edge; import com.jwetherell.algorithms.data_structures.Graph.Vertex; -/* Breath First Travesal in given "Directed graph" (Adjacany matrix) */ +/** + * Breadth-first search (BFS) is an algorithm for traversing or searching tree or graph data structures. It starts at the tree root (or some arbitrary node of a graph, sometimes referred to as a + * 'search key') and explores the neighbor nodes first, before moving to the next level neighbors. + *

+ * @see Breadth-First Search (Wikipedia) + *
+ * @author Justin Wetherell + */ public class BreadthFirstTraversal { @SuppressWarnings("unchecked") @@ -51,10 +58,11 @@ public static final > Graph.Vertex[] breadthFirstTrav // start at the source Vertex element = source; int c = 0; - int i = vertexToIndex.get(element); - visited[i] = 1; + int i = vertexToIndex.get(element); int k = 0; + arr[k] = element; + visited[i] = 1; k++; final Queue> queue = new ArrayDeque>(); @@ -68,6 +76,7 @@ public static final > Graph.Vertex[] breadthFirstTrav final Vertex v = vertices.get(i); queue.add(v); visited[i] = 1; + arr[k] = v; k++; } @@ -77,5 +86,39 @@ public static final > Graph.Vertex[] breadthFirstTrav } return arr; } + + public static int[] breadthFirstTraversal(int n, byte[][] adjacencyMatrix, int source) { + final int[] visited = new int[n]; + for (int i = 0; i < visited.length; i++) + visited[i] = -1; + + int element = source; + int i = source; + int arr[] = new int[n]; + int k = 0; + + arr[k] = element; + visited[i] = 1; + k++; + + final Queue queue = new ArrayDeque(); + queue.add(source); + while (!queue.isEmpty()) { + element = queue.peek(); + i = 0; + while (i < n) { + if (adjacencyMatrix[element][i] == 1 && visited[i] == -1) { + queue.add(i); + visited[i] = 1; + + arr[k] = i; + k++; + } + i++; + } + queue.poll(); + } + return arr; + } } diff --git a/src/com/jwetherell/algorithms/graph/ConnectedComponents.java b/src/com/jwetherell/algorithms/graph/ConnectedComponents.java index 88c05d8d..dae44174 100644 --- a/src/com/jwetherell/algorithms/graph/ConnectedComponents.java +++ b/src/com/jwetherell/algorithms/graph/ConnectedComponents.java @@ -13,9 +13,9 @@ * In graph theory, a connected component (or just component) of an undirected graph is a subgraph in which any two vertices are connected to each * other by paths, and which is connected to no additional vertices in the supergraph. A vertex with no incident edges is itself a connected * component. A graph that is itself connected has exactly one connected component, consisting of the whole graph. - * - * http://en.wikipedia.org/wiki/Connected_component_(graph_theory) - * + *

+ * @see Connected Components (Wikipedia) + *
* @author Justin Wetherell */ public class ConnectedComponents { diff --git a/src/com/jwetherell/algorithms/graph/CycleDetection.java b/src/com/jwetherell/algorithms/graph/CycleDetection.java index 276808e1..d084f16c 100644 --- a/src/com/jwetherell/algorithms/graph/CycleDetection.java +++ b/src/com/jwetherell/algorithms/graph/CycleDetection.java @@ -7,8 +7,10 @@ import com.jwetherell.algorithms.data_structures.Graph; /** - * Cycle detection in an undirected graph using depth first search. - * + * In computer science, cycle detection or cycle finding is the algorithmic problem of finding a cycle in a sequence of iterated function values. + *

+ * @see Cycle Detection (Wikipedia) + *
* @author Justin Wetherell */ public class CycleDetection { diff --git a/src/com/jwetherell/algorithms/graph/DepthFirstTraversal.java b/src/com/jwetherell/algorithms/graph/DepthFirstTraversal.java index 8d216a6b..76c5714b 100644 --- a/src/com/jwetherell/algorithms/graph/DepthFirstTraversal.java +++ b/src/com/jwetherell/algorithms/graph/DepthFirstTraversal.java @@ -1,40 +1,123 @@ package com.jwetherell.algorithms.graph; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.Stack; +import com.jwetherell.algorithms.data_structures.Graph; +import com.jwetherell.algorithms.data_structures.Graph.Edge; +import com.jwetherell.algorithms.data_structures.Graph.Vertex; + /** - * Implemented Depth First Traversal in given the "Directed graph" (Adjacency matrix) - * + * Depth-first search (DFS) is an algorithm for traversing or searching tree or graph data structures. One starts at the root (selecting some arbitrary node as the root in the case of a graph) and + * explores as far as possible along each branch before backtracking. + *

+ * @see Depth-First Search (Wikipedia) + *
* @author Justin Wetherell - * */ -class DepthFirstTraversal { +public class DepthFirstTraversal { + + @SuppressWarnings("unchecked") + public static > Graph.Vertex[] depthFirstTraversal(Graph graph, Graph.Vertex source) { + // use for look-up via index + final ArrayList> vertices = new ArrayList>(); + vertices.addAll(graph.getVertices()); + + // used for look-up via vertex + final int n = vertices.size(); + final Map,Integer> vertexToIndex = new HashMap,Integer>(); + for (int i=0; i v = vertices.get(i); + vertexToIndex.put(v,i); + } - public static int[] arr; - public static int k = 0; + // adjacency matrix + final byte[][] adj = new byte[n][n]; + for (int i=0; i v = vertices.get(i); + final int idx = vertexToIndex.get(v); + final byte[] array = new byte[n]; + adj[idx] = array; + final List> edges = v.getEdges(); + for (Edge e : edges) + array[vertexToIndex.get(e.getToVertex())] = 1; + } - public static void depthFirstTraversal(int[][] a, int[] visited,int source){ + // visited array + final byte[] visited = new byte[n]; for (int i = 0; i < visited.length; i++) visited[i] = -1; - final Stack stack = new Stack(); - int element = source; + // for holding results + final Graph.Vertex[] arr = new Graph.Vertex[n]; + + // start at the source + Vertex element = source; + int c = 0; + int i = vertexToIndex.get(element); + int k = 0; + + visited[i] = 1; + arr[k] = element; + k++; + + final Stack> stack = new Stack>(); + stack.push(source); + while (!stack.isEmpty()) { + element = stack.peek(); + c = vertexToIndex.get(element); + i = 0; + while (i < n) { + if (adj[c][i] == 1 && visited[i] == -1) { + final Vertex v = vertices.get(i); + stack.push(v); + visited[i] = 1; + + element = v; + c = vertexToIndex.get(element); + i = 0; + + arr[k] = v; + k++; + continue; + } + i++; + } + stack.pop(); + } + return arr; + } + + public static int[] depthFirstTraversal(int n, byte[][] adjacencyMatrix, int source) { + final int[] visited = new int[n]; + for (int i = 0; i < visited.length; i++) + visited[i] = -1; + + int element = source; int i = source; - int n = visited.length - 1; + int arr[] = new int[n]; + int k = 0; + + visited[source] = 1; arr[k] = element; k++; - visited[source] = 1; + + final Stack stack = new Stack(); stack.push(source); - while (!stack.isEmpty()) { element = stack.peek(); - i = element; - while (i <= n) { - if (a[element][i] == 1 && visited[i] == -1) { + i = 0; + while (i < n) { + if (adjacencyMatrix[element][i] == 1 && visited[i] == -1) { stack.push(i); visited[i] = 1; + element = i; - i = 1; + i = 0; + arr[k] = element; k++; continue; @@ -43,5 +126,6 @@ public static void depthFirstTraversal(int[][] a, int[] visited,int source){ } stack.pop(); } + return arr; } } diff --git a/src/com/jwetherell/algorithms/graph/Dijkstra.java b/src/com/jwetherell/algorithms/graph/Dijkstra.java index 46ff85ce..929cded7 100644 --- a/src/com/jwetherell/algorithms/graph/Dijkstra.java +++ b/src/com/jwetherell/algorithms/graph/Dijkstra.java @@ -13,11 +13,11 @@ /** * Dijkstra's shortest path. Only works on non-negative path weights. Returns a * tuple of total cost of shortest path and the path. - * + *

* Worst case: O(|E| + |V| log |V|) - * - * https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm - * + *

+ * @see Dijkstra's Algorithm (Wikipedia) + *
* @author Justin Wetherell */ public class Dijkstra { diff --git a/src/com/jwetherell/algorithms/graph/EdmondsKarp.java b/src/com/jwetherell/algorithms/graph/EdmondsKarp.java index 3f6a333c..1431bbfa 100644 --- a/src/com/jwetherell/algorithms/graph/EdmondsKarp.java +++ b/src/com/jwetherell/algorithms/graph/EdmondsKarp.java @@ -8,7 +8,7 @@ * In computer science, the Edmonds–Karp algorithm is an implementation of the Ford–Fulkerson method for * computing the maximum flow in a flow network in O(V*E^2) time. *

- * http://en.wikipedia.org/wiki/Edmonds%E2%80%93Karp_algorithm + * @see Edmonds-Karp Algorithm (Wikipedia) *
* @author Mateusz Cianciara * @author Justin Wetherell diff --git a/src/com/jwetherell/algorithms/graph/FloydWarshall.java b/src/com/jwetherell/algorithms/graph/FloydWarshall.java index d36a48be..b9251df6 100644 --- a/src/com/jwetherell/algorithms/graph/FloydWarshall.java +++ b/src/com/jwetherell/algorithms/graph/FloydWarshall.java @@ -9,11 +9,11 @@ /** * Floyd–Warshall algorithm is a graph analysis algorithm for finding shortest * paths in a weighted graph (with positive or negative edge weights). - * + *

* Worst case: O(V^3) - * - * https://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm - * + *

+ * @see Floyd-Warshall Algorithm (Wikipedia) + *
* @author Justin Wetherell */ public class FloydWarshall { diff --git a/src/com/jwetherell/algorithms/graph/Johnson.java b/src/com/jwetherell/algorithms/graph/Johnson.java index 8c7b1a12..5981b057 100644 --- a/src/com/jwetherell/algorithms/graph/Johnson.java +++ b/src/com/jwetherell/algorithms/graph/Johnson.java @@ -10,11 +10,11 @@ * Johnson's algorithm is a way to find the shortest paths between all pairs of * vertices in a sparse directed graph. It allows some of the edge weights to be * negative numbers, but no negative-weight cycles may exist. - * + *

* Worst case: O(V^2 log V + VE) - * - * https://en.wikipedia.org/wiki/Johnson%27s_algorithm - * + *

+ * @see Johnson's Algorithm (Wikipedia) + *
* @author Justin Wetherell */ public class Johnson { diff --git a/src/com/jwetherell/algorithms/graph/Kruskal.java b/src/com/jwetherell/algorithms/graph/Kruskal.java index 74629ffe..db21ee80 100644 --- a/src/com/jwetherell/algorithms/graph/Kruskal.java +++ b/src/com/jwetherell/algorithms/graph/Kruskal.java @@ -9,8 +9,8 @@ * subset of the edges that forms a tree that includes every vertex, where the * total weight of all the edges in the tree is minimized. *

- * https://en.wikipedia.org/wiki/Kruskal%27s_algorithm - * + * @see Kruskal's Algorithm (Wikipedia) + *
* @author Bartlomiej Drozd * @author Justin Wetherell */ diff --git a/src/com/jwetherell/algorithms/graph/Prim.java b/src/com/jwetherell/algorithms/graph/Prim.java index b8d4e366..e73724ca 100644 --- a/src/com/jwetherell/algorithms/graph/Prim.java +++ b/src/com/jwetherell/algorithms/graph/Prim.java @@ -14,7 +14,7 @@ * subset of the edges that forms a tree that includes every vertex, where the * total weight of all the edges in the tree is minimized. *

- * https://en.wikipedia.org/wiki/Prim%27s_algorithm + * @see Prim's Minimum Spanning Tree (Wikipedia) *
* @author Justin Wetherell */ diff --git a/src/com/jwetherell/algorithms/graph/PushRelabel.java b/src/com/jwetherell/algorithms/graph/PushRelabel.java index 9e4a01c9..fa5c03fa 100644 --- a/src/com/jwetherell/algorithms/graph/PushRelabel.java +++ b/src/com/jwetherell/algorithms/graph/PushRelabel.java @@ -18,7 +18,7 @@ * flow locally between neighboring nodes using push operations under the guidance of an * admissible network maintained by relabel operations. *

- * https://en.wikipedia.org/wiki/Push%E2%80%93relabel_maximum_flow_algorithm + * @see Push-Relabel Algorithm (Wikipedia) *
* @author Miron Ficak * @author Justin Wetherell diff --git a/src/com/jwetherell/algorithms/graph/TopologicalSort.java b/src/com/jwetherell/algorithms/graph/TopologicalSort.java index 732fc17f..20a2f551 100644 --- a/src/com/jwetherell/algorithms/graph/TopologicalSort.java +++ b/src/com/jwetherell/algorithms/graph/TopologicalSort.java @@ -9,9 +9,9 @@ * In computer science, a topological sort (sometimes abbreviated topsort or * toposort) or topological ordering of a directed graph is a linear ordering of * its vertices such that, for every edge uv, u comes before v in the ordering. - * - * https://en.wikipedia.org/wiki/Topological_sorting - * + *

+ * @see Topological Sort (Wikipedia) + *
* @author Justin Wetherell */ public class TopologicalSort { diff --git a/src/com/jwetherell/algorithms/graph/TurboMatching.java b/src/com/jwetherell/algorithms/graph/TurboMatching.java index 88120c82..aabaf1ba 100644 --- a/src/com/jwetherell/algorithms/graph/TurboMatching.java +++ b/src/com/jwetherell/algorithms/graph/TurboMatching.java @@ -13,9 +13,10 @@ * may incident with some edge of the matching, but this is not required and can only occur * if the number of vertices is even. *

- * https://en.wikipedia.org/wiki/Matching_(graph_theory) + * @see Matching (Wikipedia) *
* @author Jakub Szarawarski + * @author Justin Wetherell */ public class TurboMatching { @@ -27,9 +28,9 @@ public class TurboMatching { * @return a MatchingResult class instance containg a map of mates for each paired vertex and number of pairs */ public static > MatchingResult getMaximumMatching(Graph graph){ - Map, Graph.Vertex> mate = new HashMap, Graph.Vertex>(); + final Map, Graph.Vertex> mate = new HashMap, Graph.Vertex>(); - while(pathset(graph, mate)); + while (pathset(graph, mate)); return new MatchingResult(mate); } @@ -42,17 +43,15 @@ public static > MatchingResult getMaximumMatching(Gra * @return information if any augmenting path was found */ private static > boolean pathset(Graph graph, Map, Graph.Vertex> mate){ - Set> visited = new HashSet>(); + final Set> visited = new HashSet>(); boolean result = false; - - for(Graph.Vertex vertex : graph.getVertices()){ - if (mate.containsKey(vertex) == false){ + for (Graph.Vertex vertex : graph.getVertices()) { + if (mate.containsKey(vertex) == false) { if (path(graph, mate, visited, vertex)) result = true; } } - return result; } @@ -68,25 +67,24 @@ private static > boolean pathset(Graph graph, Map> boolean path(Graph graph, Map, Graph.Vertex> mate, Set> visited, Graph.Vertex vertex){ - if (visited.contains(vertex)) return false; - visited.add(vertex); - - for(Graph.Edge edge : vertex.getEdges()){ + if (visited.contains(vertex)) + return false; - Graph.Vertex neighbour = edge.getFromVertex().equals(vertex) ? edge.getToVertex() : edge.getFromVertex(); - - if (mate.containsKey(neighbour) == false || path(graph, mate, visited, mate.get(neighbour))){ + visited.add(vertex); + for (Graph.Edge edge : vertex.getEdges()) { + final Graph.Vertex neighbour = edge.getFromVertex().equals(vertex) ? edge.getToVertex() : edge.getFromVertex(); + if (mate.containsKey(neighbour) == false || path(graph, mate, visited, mate.get(neighbour))) { mate.put(vertex, neighbour); mate.put(neighbour, vertex); return true; } } - return false; } public static class MatchingResult>{ + private final Map, Graph.Vertex> mate; private final int size; diff --git a/src/com/jwetherell/algorithms/mathematics/Coprimes.java b/src/com/jwetherell/algorithms/mathematics/Coprimes.java index 0877ce40..73bf8288 100644 --- a/src/com/jwetherell/algorithms/mathematics/Coprimes.java +++ b/src/com/jwetherell/algorithms/mathematics/Coprimes.java @@ -2,10 +2,10 @@ /** * In number theory, two integers a and b are said to be relatively prime, mutually prime, or coprime (also spelled - * co-prime)[1] if the only positive integer that divides both of them is 1. That is, the only common positive factor + * co-prime) if the only positive integer that divides both of them is 1. That is, the only common positive factor * of the two numbers is 1. This is equivalent to their greatest common divisor being 1. *

- * http://en.wikipedia.org/wiki/Coprime_integers + * @see Mutually Prime / Co-prime (Wikipedia) *
* @author Szymon Stankiewicz * @author Justin Wetherell diff --git a/src/com/jwetherell/algorithms/mathematics/Exponentiation.java b/src/com/jwetherell/algorithms/mathematics/Exponentiation.java index 0b29b967..b5746a77 100644 --- a/src/com/jwetherell/algorithms/mathematics/Exponentiation.java +++ b/src/com/jwetherell/algorithms/mathematics/Exponentiation.java @@ -3,21 +3,20 @@ /** * Recursive function of exponentiation is just an implementation of definition. *

- * https://en.wikipedia.org/wiki/Exponentiation + * @see Exponentiation (Wikipedia) *

* Complexity - O(N) where N is exponent. *

* Fast exponentiation's complexity is O(lg N) *

- * https://en.wikipedia.org/wiki/Exponentiation_by_squaring + * @see Exponentiation by Squaring (Wikipedia) *
* Modular exponentiation is similar. *

- * https://en.wikipedia.org/wiki/Modular_exponentiation + * @see Modular Exponentiation (Wikipedia) *

* This implementation is the fast version of this algorithm with a complexity of O(lg N) also *
- * * @author Bartlomiej Drozd * @author Justin Wetherell */ diff --git a/src/com/jwetherell/algorithms/mathematics/FastFourierTransform.java b/src/com/jwetherell/algorithms/mathematics/FastFourierTransform.java index 93dc4126..30e2ecd8 100644 --- a/src/com/jwetherell/algorithms/mathematics/FastFourierTransform.java +++ b/src/com/jwetherell/algorithms/mathematics/FastFourierTransform.java @@ -8,7 +8,7 @@ * domain and vice versa. An FFT rapidly computes such transformations by factorizing the DFT matrix into a product of * sparse (mostly zero) factors. *

- * http://en.wikipedia.org/wiki/Fast_Fourier_transform + * @see Fast Fourier Transform (Wikipedia) *
* @author Mateusz Cianciara * @author Justin Wetherell @@ -23,7 +23,7 @@ private FastFourierTransform() { } * in terms of N1 smaller DFTs of sizes N2, recursively, to reduce the computation time to O(N log N) for highly * composite N (smooth numbers). *

- * http://en.wikipedia.org/wiki/Cooley%E2%80%93Tukey_FFT_algorithm + * @see Cooley–Tukey Algorithm (Wikipedia) *
* @param coefficients size must be power of 2 */ diff --git a/src/com/jwetherell/algorithms/mathematics/GreatestCommonDivisor.java b/src/com/jwetherell/algorithms/mathematics/GreatestCommonDivisor.java index f12889ef..4ef25cd2 100644 --- a/src/com/jwetherell/algorithms/mathematics/GreatestCommonDivisor.java +++ b/src/com/jwetherell/algorithms/mathematics/GreatestCommonDivisor.java @@ -4,7 +4,7 @@ * In mathematics, the greatest common divisor (gcd) of two or more integers, when at least one of them is not * zero, is the largest positive integer that is a divisor of both numbers. *

- * http://en.wikipedia.org/wiki/Greatest_common_divisor + * @see Greatest Common Divisor (Wikipedia) *
* @author Szymon Stankiewicz * @author Justin Wetherell @@ -30,7 +30,7 @@ public static long gcdUsingRecursion(long a, long b) { * A much more efficient method is the Euclidean algorithm, which uses a division algorithm such as long division * in combination with the observation that the gcd of two numbers also divides their difference. *

- * http://en.wikipedia.org/wiki/Greatest_common_divisor#Using_Euclid.27s_algorithm + * @see Euclidean Algorithm (Wikipedia) */ public static final long gcdUsingEuclides(long x, long y) { long greater = x; diff --git a/src/com/jwetherell/algorithms/mathematics/Knapsack.java b/src/com/jwetherell/algorithms/mathematics/Knapsack.java index c981132e..69f848c2 100644 --- a/src/com/jwetherell/algorithms/mathematics/Knapsack.java +++ b/src/com/jwetherell/algorithms/mathematics/Knapsack.java @@ -3,6 +3,15 @@ import java.util.ArrayList; import java.util.List; +/** + * The knapsack problem or rucksack problem is a problem in combinatorial optimization: Given a set of items, each with a weight and a value, determine the number of each item to include in a + * collection so that the total weight is less than or equal to a given limit and the total value is as large as possible. It derives its name from the problem faced by someone who is constrained + * by a fixed-size knapsack and must fill it with the most valuable items. + *

+ * @see Knapsack Problem (Wikipedia) + *
+ * @author Justin Wetherell + */ public class Knapsack { public static final int[] zeroOneKnapsack(int[] values, int[] weights, int capacity) { @@ -28,7 +37,7 @@ public static final int[] zeroOneKnapsack(int[] values, int[] weights, int capac } } - List list = new ArrayList(); + final List list = new ArrayList(); int i = height - 1; int j = width - 1; while (i != 0 || j != 0) { @@ -52,5 +61,4 @@ public static final int[] zeroOneKnapsack(int[] values, int[] weights, int capac return result; } - } diff --git a/src/com/jwetherell/algorithms/mathematics/Modular.java b/src/com/jwetherell/algorithms/mathematics/Modular.java index 91ece6c1..1c78de2c 100644 --- a/src/com/jwetherell/algorithms/mathematics/Modular.java +++ b/src/com/jwetherell/algorithms/mathematics/Modular.java @@ -5,7 +5,7 @@ * upon reaching a certain value—the modulus (plural moduli). The modern approach to modular arithmetic was * developed by Carl Friedrich Gauss in his book Disquisitiones Arithmeticae, published in 1801. *

- * http://en.wikipedia.org/wiki/Modular_arithmetic + * @see Modular Arithmetic (Wikipedia) *
* @author Szymon Stankiewicz * @author Justin Wetherell diff --git a/src/com/jwetherell/algorithms/mathematics/Permutations.java b/src/com/jwetherell/algorithms/mathematics/Permutations.java index a9ec3fb8..144a17c4 100644 --- a/src/com/jwetherell/algorithms/mathematics/Permutations.java +++ b/src/com/jwetherell/algorithms/mathematics/Permutations.java @@ -7,7 +7,7 @@ * In mathematics, the notion of permutation relates to the act of arranging all the members of a set into some sequence * or order, or if the set is already ordered, rearranging (reordering) its elements, a process called permuting. *

- * http://en.wikipedia.org/wiki/Permutation + * @see Permutation (Wikipedia) *
* @author Justin Wetherell * @author Lucjan Roslanowski diff --git a/src/com/jwetherell/algorithms/mathematics/Primes.java b/src/com/jwetherell/algorithms/mathematics/Primes.java index c6ec298c..ee4ca62b 100644 --- a/src/com/jwetherell/algorithms/mathematics/Primes.java +++ b/src/com/jwetherell/algorithms/mathematics/Primes.java @@ -17,7 +17,7 @@ public class Primes { * of determining these factors is called integer factorization. The fundamental theorem of arithmetic says that every positive * integer has a single unique prime factorization. *

- * https://en.wikipedia.org/wiki/Prime_factor + * @see Prime Factor (Wikipedia) *
*/ public static final Map getPrimeFactorization(long number) { @@ -94,7 +94,7 @@ public static final boolean isPrime(long number) { * number, 2. The multiples of a given prime are generated as a sequence of numbers starting from that prime, with constant * difference between them that is equal to that prime. *

- * https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes + * @see Sieve of Eratosthenes (Wikipedia) *
*/ public static final boolean sieveOfEratosthenes(int number) { @@ -128,7 +128,7 @@ public static final boolean sieveOfEratosthenes(int number) { * algorithm, witnesses are not randomized. Used set of witnesses guarantees that result * will be correct for sure (not probably) for any number lower than 10^18. *

- * https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test + * @see Miller-Rabin Primality Test (Wikipedia) *
*/ public static final boolean millerRabinTest(int number) { diff --git a/src/com/jwetherell/algorithms/mathematics/RamerDouglasPeucker.java b/src/com/jwetherell/algorithms/mathematics/RamerDouglasPeucker.java index eca8a3b2..e43d24c9 100644 --- a/src/com/jwetherell/algorithms/mathematics/RamerDouglasPeucker.java +++ b/src/com/jwetherell/algorithms/mathematics/RamerDouglasPeucker.java @@ -6,9 +6,9 @@ /** * The Ramer–Douglas–Peucker algorithm (RDP) is an algorithm for reducing the number of points in a * curve that is approximated by a series of points. - * - * http://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm - * + *

+ * @see Ramer–Douglas–Peucker Algorithm (Wikipedia) + *
* @author Justin Wetherell */ public class RamerDouglasPeucker { diff --git a/src/com/jwetherell/algorithms/numbers/Complex.java b/src/com/jwetherell/algorithms/numbers/Complex.java index 48b1a834..bef753d4 100644 --- a/src/com/jwetherell/algorithms/numbers/Complex.java +++ b/src/com/jwetherell/algorithms/numbers/Complex.java @@ -5,7 +5,7 @@ * imaginary unit, satisfying the equation i2 = −1.[1] In this expression, a is the real part and b is the imaginary * part of the complex number. If z=a+bi z=a+bi, then Rz=a, Iz=b. *

- * http://en.wikipedia.org/wiki/Complex_number + * @see Complex Number (Wikipedia) *
* @author Mateusz Cianciara * @author Justin Wetherell diff --git a/src/com/jwetherell/algorithms/search/BinarySearch.java b/src/com/jwetherell/algorithms/search/BinarySearch.java index fabff71c..8d3f8521 100644 --- a/src/com/jwetherell/algorithms/search/BinarySearch.java +++ b/src/com/jwetherell/algorithms/search/BinarySearch.java @@ -9,9 +9,9 @@ * Best-case performance O(1)
* Average performance O(log n)
* Worst-case space complexity O(1)
+ *

+ * @see Binary Search (Wikipedia) *
- * https://en.wikipedia.org/wiki/Binary_search_algorithm - * * @author Justin Wetherell */ public class BinarySearch { diff --git a/src/com/jwetherell/algorithms/search/InterpolationSearch.java b/src/com/jwetherell/algorithms/search/InterpolationSearch.java index c3798292..d9050256 100644 --- a/src/com/jwetherell/algorithms/search/InterpolationSearch.java +++ b/src/com/jwetherell/algorithms/search/InterpolationSearch.java @@ -6,9 +6,9 @@ *

* Worst-case performance O(n)
* Average performance O(log(log(n)))
+ *

+ * @see Interpolation Search (Wikipedia) *
- * https://en.wikipedia.org/wiki/Interpolation_search - * * @author Justin Wetherell */ public class InterpolationSearch { diff --git a/src/com/jwetherell/algorithms/search/LinearSearch.java b/src/com/jwetherell/algorithms/search/LinearSearch.java index a811240b..196591e7 100644 --- a/src/com/jwetherell/algorithms/search/LinearSearch.java +++ b/src/com/jwetherell/algorithms/search/LinearSearch.java @@ -8,9 +8,9 @@ * Best-case performance O(1)
* Average performance O(n)
* Worst-case space complexity O(1)
+ *

+ * @see Linear Search (Wikipedia) *
- * https://en.wikipedia.org/wiki/Linear_search - * * @author Justin Wetherell */ public class LinearSearch { diff --git a/src/com/jwetherell/algorithms/search/LowerBound.java b/src/com/jwetherell/algorithms/search/LowerBound.java index ae028fb0..569e4532 100644 --- a/src/com/jwetherell/algorithms/search/LowerBound.java +++ b/src/com/jwetherell/algorithms/search/LowerBound.java @@ -1,15 +1,16 @@ package com.jwetherell.algorithms.search; /** - * Lower bound search algorithm. - * Lower bound is kind of binary search algorithm but: - * -If searched element doesn't exist function returns index of first element which is bigger than searched value. - * -If searched element is bigger than any array element function returns first index after last element. - * -If searched element is lower than any array element function returns index of first element. - * -If there are many values equals searched value function returns first occurrence. + * Lower bound search algorithm.
+ * Lower bound is kind of binary search algorithm but:
+ * -If searched element doesn't exist function returns index of first element which is bigger than searched value.
+ * -If searched element is bigger than any array element function returns first index after last element.
+ * -If searched element is lower than any array element function returns index of first element.
+ * -If there are many values equals searched value function returns first occurrence.
* Behaviour for unsorted arrays is unspecified. + *

* Complexity O(log n). - * + *

* @author Bartlomiej Drozd * @author Justin Wetherell */ diff --git a/src/com/jwetherell/algorithms/search/QuickSelect.java b/src/com/jwetherell/algorithms/search/QuickSelect.java index f7bc20ef..3fe048a9 100644 --- a/src/com/jwetherell/algorithms/search/QuickSelect.java +++ b/src/com/jwetherell/algorithms/search/QuickSelect.java @@ -8,9 +8,9 @@ * Worst-case performance О(n2)
* Best-case performance О(n)
* Average performance O(n)
+ *

+ * @see Quickselect (Wikipedia) *
- * https://en.wikipedia.org/wiki/Quickselect - * * @author Justin Wetherell */ public class QuickSelect { diff --git a/src/com/jwetherell/algorithms/search/UpperBound.java b/src/com/jwetherell/algorithms/search/UpperBound.java index 803dfb57..5c6d8a21 100644 --- a/src/com/jwetherell/algorithms/search/UpperBound.java +++ b/src/com/jwetherell/algorithms/search/UpperBound.java @@ -1,13 +1,15 @@ package com.jwetherell.algorithms.search; /** - * Upper bound search algorithm. - * Upper bound is kind of binary search algorithm but: - * -It returns index of first element which is grater than searched value. - * -If searched element is bigger than any array element function returns first index after last element. + * Upper bound search algorithm.
+ * Upper bound is kind of binary search algorithm but:
+ * -It returns index of first element which is grater than searched value.
+ * -If searched element is bigger than any array element function returns first index after last element.
+ *
* Behaviour for unsorted arrays is unspecified. + *

* Complexity O(log n). - * + *
* @author Bartlomiej Drozd * @author Justin Wetherell */ diff --git a/src/com/jwetherell/algorithms/sequence/ArithmeticProgression.java b/src/com/jwetherell/algorithms/sequence/ArithmeticProgression.java index f8c1b3a5..50fad654 100644 --- a/src/com/jwetherell/algorithms/sequence/ArithmeticProgression.java +++ b/src/com/jwetherell/algorithms/sequence/ArithmeticProgression.java @@ -3,7 +3,7 @@ /** * Compute the result of adding a sequence of numbers from N (startNumber) to N+X (startNumber+numberOfNumbersToCompute) *

- * https://en.wikipedia.org/wiki/Arithmetic_progression + * @see Arithmetic Progression (Wikipedia) *
* @author Justin Wetherell */ @@ -30,7 +30,7 @@ public static final long sequenceTotalUsingLoop(int startNumber, int numberOfNum *

* e.g. result = N + (N+1) + (N+2) + (N+3) + ..... + (N+X)
*
- * https://en.wikipedia.org/wiki/Triangular_number + * @see Triangular Number (Wikipedia) */ public static final long sequenceTotalUsingTriangularNumbers(int startNumber, int numberOfNumbersToCompute) { // n*(n+1)/2 diff --git a/src/com/jwetherell/algorithms/sequence/FibonacciSequence.java b/src/com/jwetherell/algorithms/sequence/FibonacciSequence.java index 283bcc86..7626a42d 100644 --- a/src/com/jwetherell/algorithms/sequence/FibonacciSequence.java +++ b/src/com/jwetherell/algorithms/sequence/FibonacciSequence.java @@ -4,8 +4,7 @@ * In mathematics, the Fibonacci numbers are the numbers in the following integer sequence, called the Fibonacci sequence, and characterized by the fact that every number after the first two is the * sum of the two preceding ones: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ... *

- * - * https://en.wikipedia.org/wiki/Fibonacci_number + * @see Fibonacci Sequence (Wikipedia) *
* @author Justin Wetherell */ diff --git a/src/com/jwetherell/algorithms/sequence/LargestSumContiguousSubarray.java b/src/com/jwetherell/algorithms/sequence/LargestSumContiguousSubarray.java index cc82f8ec..87f8da9c 100644 --- a/src/com/jwetherell/algorithms/sequence/LargestSumContiguousSubarray.java +++ b/src/com/jwetherell/algorithms/sequence/LargestSumContiguousSubarray.java @@ -4,7 +4,7 @@ * Given an array of integers, we want to find the largest sum of contiguous * subarray. *

- * https://en.wikipedia.org/wiki/Maximum_subarray_problem + * @see Maximum Subarray Problem (Wikipedia) *
* @author Miguel Stephane KAKANAKOU * @author Justin Wetherell diff --git a/src/com/jwetherell/algorithms/sequence/LongestCommonSubsequence.java b/src/com/jwetherell/algorithms/sequence/LongestCommonSubsequence.java index fa807cd4..66fa392f 100644 --- a/src/com/jwetherell/algorithms/sequence/LongestCommonSubsequence.java +++ b/src/com/jwetherell/algorithms/sequence/LongestCommonSubsequence.java @@ -7,7 +7,7 @@ * The longest common subsequence (LCS) problem is the problem of finding the longest subsequence common to all sequences in a set of sequences (often just two sequences). It differs from problems * of finding common substrings: unlike substrings, subsequences are not required to occupy consecutive positions within the original sequences. *

- * https://en.wikipedia.org/wiki/Longest_common_subsequence_problem + * @see Longest Common Subsequence Problem (Wikipedia) *
* @author Justin Wetherell */ diff --git a/src/com/jwetherell/algorithms/sequence/LongestIncreasingSubsequence.java b/src/com/jwetherell/algorithms/sequence/LongestIncreasingSubsequence.java index cdb39de8..4421896b 100644 --- a/src/com/jwetherell/algorithms/sequence/LongestIncreasingSubsequence.java +++ b/src/com/jwetherell/algorithms/sequence/LongestIncreasingSubsequence.java @@ -8,7 +8,7 @@ * In computer science, the longest increasing subsequence problem is to find a subsequence of a given sequence in which the subsequence's elements are in sorted order, lowest to highest, and in * which the subsequence is as long as possible. This subsequence is not necessarily contiguous, or unique. *

- * https://en.wikipedia.org/wiki/Longest_increasing_subsequence + * @see Longest Increasing Subsequence Problem (Wikipedia) *
* @author Bartlomiej Drozd * @author Justin Wetherell diff --git a/src/com/jwetherell/algorithms/sequence/LongestPalindromicSubsequence.java b/src/com/jwetherell/algorithms/sequence/LongestPalindromicSubsequence.java index 040d270c..9d870978 100644 --- a/src/com/jwetherell/algorithms/sequence/LongestPalindromicSubsequence.java +++ b/src/com/jwetherell/algorithms/sequence/LongestPalindromicSubsequence.java @@ -4,17 +4,17 @@ * A longest palin­dromic sub­se­quence is a sequence that appears in the same * rel­a­tive order, but not nec­es­sar­ily contiguous(not sub­string) and * palin­drome in nature. - * - * Given a string, find the length of the longest palin­dromic sub­se­quence in - * it. - * + *

+ * Given a string, find the length of the longest palin­dromic sub­se­quence in it. + *

+ * @see Longest Palin­dromic Sub­se­quence (Wikipedia) + *
* @author Miguel Stephane KAKANAKOU - * + * @author Justin Wetherell */ public class LongestPalindromicSubsequence { - private LongestPalindromicSubsequence() { - } + private LongestPalindromicSubsequence() { } /** * Find the length of the longest palin­dromic sub­se­quence in the given @@ -23,9 +23,11 @@ private LongestPalindromicSubsequence() { public static int getLongestPalindromeSubsequence(String s) { if (s == null) throw new NullPointerException("The given String is null"); - int len = s.length(); - int[][] M = new int[len][len]; - char[] ch = s.toCharArray(); + + final int len = s.length(); + final int[][] M = new int[len][len]; + final char[] ch = s.toCharArray(); + initializeMatrix(M); fillMatrix(M, ch); return M[0][len-1]; @@ -44,7 +46,7 @@ private static void initializeMatrix(int[][] M) { } private static void fillMatrix(int[][] M, char[] ch) { - int len = M.length; + final int len = M.length; int i, j; for (int k=1; k - * http://www.geeksforgeeks.org/find-number-times-string-occurs-given-string/ + * @see Substring occurs in String (GeeksForGeeks) *
* @author Justin Wetherell */ diff --git a/src/com/jwetherell/algorithms/sorts/AmericanFlagSort.java b/src/com/jwetherell/algorithms/sorts/AmericanFlagSort.java index 0ff11cda..7015a147 100644 --- a/src/com/jwetherell/algorithms/sorts/AmericanFlagSort.java +++ b/src/com/jwetherell/algorithms/sorts/AmericanFlagSort.java @@ -6,16 +6,19 @@ * algorithms such as radix sort and American flag sort are typically used to * sort large objects such as strings, for which comparison is not a unit-time * operation. - * - * Family: Bucket. - * Space: In-place. - * Stable: False. - * - * Average case = O(n*k/d) Worst case = O(n*k/d) Best case = O(n*k/d) + *

+ * Family: Bucket.
+ * Space: In-place.
+ * Stable: False.
+ *

+ * Average case = O(n*k/d)
+ * Worst case = O(n*k/d)
+ * Best case = O(n*k/d)
+ *

* NOTE: n is the number of digits and k is the average bucket size - * - * http://en.wikipedia.org/wiki/American_flag_sort - * + *

+ * @see American Flag Sort (Wikipedia) + *
* @author Justin Wetherell */ public class AmericanFlagSort { diff --git a/src/com/jwetherell/algorithms/sorts/BubbleSort.java b/src/com/jwetherell/algorithms/sorts/BubbleSort.java index b91a066d..3ac320ff 100644 --- a/src/com/jwetherell/algorithms/sorts/BubbleSort.java +++ b/src/com/jwetherell/algorithms/sorts/BubbleSort.java @@ -5,15 +5,17 @@ * through the list to be sorted, comparing each pair of adjacent items and * swapping them if they are in the wrong order. The pass through the list is * repeated until no swaps are needed, which indicates that the list is sorted. - * - * Family: Exchanging. - * Space: In-place. - * Stable: True. - * - * Average case = O(n^2) Worst case = O(n^2) Best case = O(n) - * - * http://en.wikipedia.org/wiki/Bubble_sort - * + *

+ * Family: Exchanging.
+ * Space: In-place.
+ * Stable: True.
+ *

+ * Average case = O(n^2)
+ * Worst case = O(n^2)
+ * Best case = O(n)
+ *

+ * @see Bubble Sort (Wikipedia) + *
* @author Justin Wetherell */ public class BubbleSort> { diff --git a/src/com/jwetherell/algorithms/sorts/CountingSort.java b/src/com/jwetherell/algorithms/sorts/CountingSort.java index d2d177b0..f1593c50 100644 --- a/src/com/jwetherell/algorithms/sorts/CountingSort.java +++ b/src/com/jwetherell/algorithms/sorts/CountingSort.java @@ -6,16 +6,19 @@ * It operates by counting the number of objects that have each distinct key * value, and using arithmetic on those counts to determine the positions of * each key value in the output sequence. - * - * Family: Counting. - * Space: An Array of length r. - * Stable: True. - * - * Average case = O(n+r) Worst case = O(n+r) Best case = O(n+r) + *

+ * Family: Counting.
+ * Space: An Array of length r.
+ * Stable: True.
+ *

+ * Average case = O(n+r)
+ * Worst case = O(n+r)
+ * Best case = O(n+r)
+ *

* NOTE: r is the range of numbers (0 to r) to be sorted. - * - * http://en.wikipedia.org/wiki/Counting_sort - * + *

+ * @see Counting Sort (Wikipedia) + *
* @author Justin Wetherell */ public class CountingSort { diff --git a/src/com/jwetherell/algorithms/sorts/HeapSort.java b/src/com/jwetherell/algorithms/sorts/HeapSort.java index 1e5b7d6f..6991347d 100644 --- a/src/com/jwetherell/algorithms/sorts/HeapSort.java +++ b/src/com/jwetherell/algorithms/sorts/HeapSort.java @@ -5,15 +5,17 @@ * list), and is part of the selection sort family. Although somewhat slower in * practice on most machines than a well-implemented quicksort, it has the * advantage of a more favorable worst-case O(n log n) runtime. - * - * Family: Selection. - * Space: In-place. - * Stable: False. - * - * Average case = O(n*log n) Worst case = O(n*log n) Best case = O(n*log n) - * - * http://en.wikipedia.org/wiki/Heap_sort - * + *

+ * Family: Selection.
+ * Space: In-place.
+ * Stable: False.
+ *

+ * Average case = O(n*log n)
+ * Worst case = O(n*log n)
+ * Best case = O(n*log n)
+ *

+ * @see Heap Sort (Wikipedia) + *
* @author Justin Wetherell */ public class HeapSort> { diff --git a/src/com/jwetherell/algorithms/sorts/InsertionSort.java b/src/com/jwetherell/algorithms/sorts/InsertionSort.java index c9772940..6aedf610 100644 --- a/src/com/jwetherell/algorithms/sorts/InsertionSort.java +++ b/src/com/jwetherell/algorithms/sorts/InsertionSort.java @@ -5,15 +5,17 @@ * sorted array (or list) is built one entry at a time. It is much less * efficient on large lists than more advanced algorithms such as quicksort, * heapsort, or merge sort. - * - * Family: Insertion. - * Space: In-place. - * Stable: True. - * - * Average case = O(n^2) Worst case = O(n^2) Best case = O(n) - * - * http://en.wikipedia.org/wiki/Insertion_sort - * + *

+ * Family: Insertion.
+ * Space: In-place.
+ * Stable: True.
+ *

+ * Average case = O(n^2)
+ * Worst case = O(n^2)
+ * Best case = O(n)
+ *

+ * @see Insertion Sort (Wikipedia) + *
* @author Justin Wetherell */ public class InsertionSort> { diff --git a/src/com/jwetherell/algorithms/sorts/MergeSort.java b/src/com/jwetherell/algorithms/sorts/MergeSort.java index bc7d4dd4..69823f81 100644 --- a/src/com/jwetherell/algorithms/sorts/MergeSort.java +++ b/src/com/jwetherell/algorithms/sorts/MergeSort.java @@ -4,15 +4,17 @@ * Merge sort is an O(n log n) comparison-based sorting algorithm. Most * implementations produce a stable sort, which means that the implementation * preserves the input order of equal elements in the sorted output. - * - * Family: Merging. - * Space: In-place. - * Stable: True. - * - * Average case = O(n*log n) Worst case = O(n*log n) Best case = O(n*log n) - * - * http://en.wikipedia.org/wiki/Merge_sort - * + *

+ * Family: Merging.
+ * Space: In-place.
+ * Stable: True.
+ *

+ * Average case = O(n*log n)
+ * Worst case = O(n*log n)
+ * Best case = O(n*log n)
+ *

+ * @see Merge Sort (Wikipedia) + *
* @author Justin Wetherell */ @SuppressWarnings("unchecked") diff --git a/src/com/jwetherell/algorithms/sorts/QuickSort.java b/src/com/jwetherell/algorithms/sorts/QuickSort.java index 2328ffa2..7484942b 100644 --- a/src/com/jwetherell/algorithms/sorts/QuickSort.java +++ b/src/com/jwetherell/algorithms/sorts/QuickSort.java @@ -6,15 +6,17 @@ * Quicksort is a sorting algorithm which, on average, makes O(n*log n) comparisons to sort * n items. In the worst case, it makes O(n^2) comparisons, though this behavior is * rare. Quicksort is often faster in practice than other algorithms. - * - * Family: Divide and conquer. - * Space: In-place. - * Stable: False. - * - * Average case = O(n*log n), Worst case = O(n^2), Best case = O(n) [three-way partition and equal keys] - * - * http://en.wikipedia.org/wiki/Quick_sort - * + *

+ * Family: Divide and conquer.
+ * Space: In-place.
+ * Stable: False.
+ *

+ * Average case = O(n*log n)
+ * Worst case = O(n^2)
+ * Best case = O(n) [three-way partition and equal keys]
+ *

+ * @see Quicksort (Wikipedia) + *
* @author Justin Wetherell */ public class QuickSort> { diff --git a/src/com/jwetherell/algorithms/sorts/RadixSort.java b/src/com/jwetherell/algorithms/sorts/RadixSort.java index 5d0f945d..299f6fcb 100644 --- a/src/com/jwetherell/algorithms/sorts/RadixSort.java +++ b/src/com/jwetherell/algorithms/sorts/RadixSort.java @@ -9,16 +9,19 @@ * because integers can represent strings of characters (e.g., names or dates) * and specially formatted floating point numbers, radix sort is not limited to * integers. - * - * Family: Bucket. - * Space: 10 Buckets with at most n integers per bucket. - * Stable: True. - * - * Average case = O(n*k) Worst case = O(n*k) Best case = O(n*k) + *

+ * Family: Bucket.
+ * Space: 10 Buckets with at most n integers per bucket.
+ * Stable: True.
+ *

+ * Average case = O(n*k)
+ * Worst case = O(n*k)
+ * Best case = O(n*k)
+ *

* NOTE: n is the number of digits and k is the average bucket size - * - * http://en.wikipedia.org/wiki/Radix_sort - * + *

+ * @see Radix Sort (Wikipedia) + *
* @author Justin Wetherell */ public class RadixSort { diff --git a/src/com/jwetherell/algorithms/sorts/ShellSort.java b/src/com/jwetherell/algorithms/sorts/ShellSort.java index 293dad31..c94e7fed 100644 --- a/src/com/jwetherell/algorithms/sorts/ShellSort.java +++ b/src/com/jwetherell/algorithms/sorts/ShellSort.java @@ -9,17 +9,21 @@ * bubble sort, by starting the comparison and exchange of elements with * elements that are far apart before finishing with neighboring elements. * Starting with far apart elements can move some out-of-place elements into - * position faster than a simple nearest neighbor exchange. Family: Exchanging. - * Space: In-place. Stable: False. - * - * Average case = depends on the gap Worst case = O(n * log^2 n) Best case = - * O(n) - * - * http://en.wikipedia.org/wiki/Shell_sort - * + * position faster than a simple nearest neighbor exchange. + *

+ * Family: Exchanging.
+ * Space: In-place.
+ * Stable: False.
+ *

+ * Average case = depends on the gap
+ * Worst case = O(n * log^2 n)
+ * Best case = O(n)
+ *

+ * @see Shell Sort (Wikipedia) + *
* @author Justin Wetherell */ -public abstract class ShellSort> { +public class ShellSort> { private ShellSort() { } diff --git a/src/com/jwetherell/algorithms/strings/KnuthMorrisPratt.java b/src/com/jwetherell/algorithms/strings/KnuthMorrisPratt.java index 361ccd31..97806084 100644 --- a/src/com/jwetherell/algorithms/strings/KnuthMorrisPratt.java +++ b/src/com/jwetherell/algorithms/strings/KnuthMorrisPratt.java @@ -8,8 +8,8 @@ * Prefix-suffix of string S is a substring which occurs at the beginning and at the end of S. *

* Time complexity: O(n)
- *
- * https://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm + *

+ * @see Knuth Morris Pratt (Wikipedia) *
* @author Szymon Stankiewicz * @author Justin Wetherell @@ -22,14 +22,11 @@ private KnuthMorrisPratt() {} * This function implements KMP algorithm for finding length of maximal prefix-suffix for each prefix of the string. * Prefix-suffix of string S is a substring which occurs at the beginning and at the end of S. *

- * Time complexity: O(n)

- *

- * https://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm - *
* @param text Text * @return maximal length of prefix-suffix for each prefix of the string text */ public static List getPrefSufTable(String text) { + final List prefSufTable = new ArrayList(); final char[] chars = text.toCharArray(); diff --git a/src/com/jwetherell/algorithms/strings/Manacher.java b/src/com/jwetherell/algorithms/strings/Manacher.java index af715875..eab8d5c4 100644 --- a/src/com/jwetherell/algorithms/strings/Manacher.java +++ b/src/com/jwetherell/algorithms/strings/Manacher.java @@ -6,10 +6,10 @@ *

* The longest palindromic substring problem should not be confused with * the different problem of finding the longest palindromic subsequence. - *
+ *

* Manacher's algorithm finds the longest palindromic substring in linear time O(n); where n = length(input) - *
- * https://en.wikipedia.org/wiki/Longest_palindromic_substring#Manacher.27s_algorithm + *

+ * @see Manacher's Algorithm (Wikipedia) *
* @author Piotr Kruk * @author Justin Wetherell diff --git a/src/com/jwetherell/algorithms/strings/Rotation.java b/src/com/jwetherell/algorithms/strings/Rotation.java index c92ebb0f..09d8520d 100644 --- a/src/com/jwetherell/algorithms/strings/Rotation.java +++ b/src/com/jwetherell/algorithms/strings/Rotation.java @@ -4,7 +4,7 @@ * Rotation of the string is some cyclic transformation of that string. * More formally a string s = uv is said to be a rotation of t if t = vu. *

- * http://en.wikipedia.org/wiki/String_(computer_science)#Rotations + * @see String Rotation (Wikipedia) *
* @Author Szymon Stankiewicz * @author Justin Wetherell @@ -57,11 +57,12 @@ private static String bestRotation(String text, boolean greatest) { * lowest lexicographical order of all such rotations. * Finding the lexicographically minimal rotation is useful as a way of normalizing strings. *

- * http://en.wikipedia.org/wiki/Lexicographically_minimal_string_rotation - *
+ * @see Lexicographically Minimal String Rotation (Wikipedia) + *

* This function implements Duval's algorithm. - *
- * http://en.wikipedia.org/wiki/Lexicographically_minimal_string_rotation#Duval.27s_Lyndon_Factorization_Algorithm + *

+ * @see Duval's Algorithm (Wikipedia) + *

* Complexity: O(n) *
* @param text @@ -77,11 +78,11 @@ public static String getLexicographicallyMinimalRotation(String text) { * highest lexicographical order of all such rotations. * Finding the lexicographically maximal rotation is useful as a way of normalizing strings. *

- * http://en.wikipedia.org/wiki/Lexicographically_minimal_string_rotation - *
+ * @see Lexicographically Minimal String Rotation (Wikipedia) + *

* This function implements Duval's algorithm. - * http://en.wikipedia.org/wiki/Lexicographically_minimal_string_rotation#Duval.27s_Lyndon_Factorization_Algorithm - *
+ * @see Duval's Algorithm (Wikipedia) + *

* Complexity: O(n) *
* @param text diff --git a/src/com/jwetherell/algorithms/strings/StringFunctions.java b/src/com/jwetherell/algorithms/strings/StringFunctions.java index a4e05234..8b9cdb41 100644 --- a/src/com/jwetherell/algorithms/strings/StringFunctions.java +++ b/src/com/jwetherell/algorithms/strings/StringFunctions.java @@ -5,7 +5,7 @@ /** * This class contains methods for modifying text. - * + *

* @author Justin Wetherell */ public class StringFunctions { diff --git a/test/com/jwetherell/algorithms/data_structures/test/LCPArrayTest.java b/test/com/jwetherell/algorithms/data_structures/test/LCPArrayTest.java index 3bfbe3fa..4fea9863 100644 --- a/test/com/jwetherell/algorithms/data_structures/test/LCPArrayTest.java +++ b/test/com/jwetherell/algorithms/data_structures/test/LCPArrayTest.java @@ -13,7 +13,7 @@ public class LCPArrayTest { @Test public void smallTest(){ String string = "asdasdd"; - LCPArray LCPArrayBuilder = new LCPArray(string); + LCPArray LCPArrayBuilder = new LCPArray(string); ArrayList LCPArray = LCPArrayBuilder.getLCPArray(); ArrayList result = new ArrayList(); @@ -24,9 +24,8 @@ public void smallTest(){ @Test public void longTest(){ - String string = "aasfaasdsadasdfasdasdasdasfdasfassdfas"; - LCPArray LCPArrayBuilder = new LCPArray(string); + LCPArray LCPArrayBuilder = new LCPArray(string); ArrayList LCPArray = LCPArrayBuilder.getLCPArray(); ArrayList result = new ArrayList(); @@ -38,9 +37,8 @@ public void longTest(){ @Test public void singleLetterTest(){ - String string = "aaaaaaaaaaaa"; - LCPArray LCPArrayBuilder = new LCPArray(string); + LCPArray LCPArrayBuilder = new LCPArray(string); ArrayList LCPArray = LCPArrayBuilder.getLCPArray(); ArrayList result = new ArrayList(); diff --git a/test/com/jwetherell/algorithms/data_structures/test/common/HeapTest.java b/test/com/jwetherell/algorithms/data_structures/test/common/HeapTest.java index 3c92e2e8..b580f666 100644 --- a/test/com/jwetherell/algorithms/data_structures/test/common/HeapTest.java +++ b/test/com/jwetherell/algorithms/data_structures/test/common/HeapTest.java @@ -7,28 +7,6 @@ public class HeapTest { - /** - * Test the heap invariants. - * - * In computer science, a heap is a specialized tree-based data structure that satisfies the heap property: If A is a parent - * node of B then the key of node A is ordered with respect to the key of node B with the same ordering applying across the - * heap. Either the keys of parent nodes are always greater than or equal to those of the children and the highest key is in - * the root node (this kind of heap is called max heap) or the keys of parent nodes are less than or equal to those of the - * children and the lowest key is in the root node (min heap). - * - * http://en.wikipedia.org/wiki/Heap_(data_structure) - * - * @author Justin Wetherell - * - * @param heapType Type of heap (Min or Max). - * @param heap Heap to test. - * @param type Type of data in the heap (Either String or Integer). - * @param name Name used in debug. - * @param unsorted Unsorted test data. - * @param sorted Sorted test data. - * @param invalid Invalid data which isn't in the data-structure. - * @return True if the heap passes it's invariants tests. - */ public static > boolean testHeap(BinaryHeap.Type heapType, IHeap heap, Class type, String name, Integer[] unsorted, Integer[] sorted, Integer _invalid) { for (int i = 0; i < unsorted.length; i++) { diff --git a/test/com/jwetherell/algorithms/data_structures/test/common/IteratorTest.java b/test/com/jwetherell/algorithms/data_structures/test/common/IteratorTest.java index db4f92c6..fd30f061 100644 --- a/test/com/jwetherell/algorithms/data_structures/test/common/IteratorTest.java +++ b/test/com/jwetherell/algorithms/data_structures/test/common/IteratorTest.java @@ -4,16 +4,6 @@ public class IteratorTest { - /** - * In object-oriented computer programming, an iterator is an object that enables a programmer to traverse a container. - * - * http://en.wikipedia.org/wiki/Iterator - * - * @author Justin Wetherell - * - * @param iter Iterator to test. - * @return True if iterator passes invariant tests. - */ public static > boolean testIterator(Iterator iter) { while (iter.hasNext()) { T item = iter.next(); diff --git a/test/com/jwetherell/algorithms/data_structures/test/common/JavaCollectionTest.java b/test/com/jwetherell/algorithms/data_structures/test/common/JavaCollectionTest.java index fdf9db50..12e790a7 100644 --- a/test/com/jwetherell/algorithms/data_structures/test/common/JavaCollectionTest.java +++ b/test/com/jwetherell/algorithms/data_structures/test/common/JavaCollectionTest.java @@ -4,22 +4,6 @@ public class JavaCollectionTest { - /** - * In computer science, a collection or container is a grouping of some variable number of data items - * (possibly zero) that have some shared significance to the problem being solved and need to be operated - * upon together in some controlled fashion. - * - * http://en.wikipedia.org/wiki/Collection_(abstract_data_type) - * - * @author Justin Wetherell - * - * @param collection Collection to test. - * @param type Type of data in the collection (Either String or Integer). - * @param name name Name used in debug. - * @param unsorted Unsorted test data. - * @param sorted Sorted test data. - * @return True if the collection passes it's invariants tests. - */ public static > boolean testCollection(Collection collection, Class type, String name, Integer[] unsorted, Integer[] sorted, Integer _invalid) { // Make sure the collection is empty diff --git a/test/com/jwetherell/algorithms/data_structures/test/common/JavaMapTest.java b/test/com/jwetherell/algorithms/data_structures/test/common/JavaMapTest.java index 9f2f0a57..df74fbdd 100644 --- a/test/com/jwetherell/algorithms/data_structures/test/common/JavaMapTest.java +++ b/test/com/jwetherell/algorithms/data_structures/test/common/JavaMapTest.java @@ -3,23 +3,6 @@ @SuppressWarnings("unchecked") public class JavaMapTest { - /** - * In computer science, an associative array, map, symbol table, or dictionary is an abstract data - * type composed of a collection of (key, value) pairs, such that each possible key appears at most - * once in the collection. - * - * http://en.wikipedia.org/wiki/Associative_array - * - * @author Justin Wetherell - * - * @param map Map to test. - * @param type Type of data in the map (Either String or Integer). - * @param name Name used in debug. - * @param Unsorted test data. - * @param sorted Sorted test data. - * @param invalid Invalid data which isn't in the data-structure. - * @return True if the map passes it's invariants tests. - */ public static > boolean testJavaMap(java.util.Map map, Class type, String name, Integer[] unsorted, Integer[] sorted, Integer _invalid) { // Make sure the map is empty diff --git a/test/com/jwetherell/algorithms/data_structures/test/common/ListIteratorTest.java b/test/com/jwetherell/algorithms/data_structures/test/common/ListIteratorTest.java index 50ea8879..0d2eb1a1 100644 --- a/test/com/jwetherell/algorithms/data_structures/test/common/ListIteratorTest.java +++ b/test/com/jwetherell/algorithms/data_structures/test/common/ListIteratorTest.java @@ -5,19 +5,6 @@ public class ListIteratorTest { - /** - * An iterator for lists that allows the programmer to traverse the list in either direction, - * modify the list during iteration, and obtain the iterator's current position in the list. - * - * http://en.wikipedia.org/wiki/Iterator - * - * @author Justin Wetherell - * - * @param iter List iterator to test. - * @param data Test data to test against. - * @param size Size of the test data. - * @return True if list iterator passes it's invariant tests. - */ public static > boolean testListIterator(ListIterator iter, Class type, Integer[] data, int size) { // Make sure you catch going prev at the start diff --git a/test/com/jwetherell/algorithms/data_structures/test/common/ListTest.java b/test/com/jwetherell/algorithms/data_structures/test/common/ListTest.java index e3875f54..67b5914d 100644 --- a/test/com/jwetherell/algorithms/data_structures/test/common/ListTest.java +++ b/test/com/jwetherell/algorithms/data_structures/test/common/ListTest.java @@ -4,20 +4,6 @@ public class ListTest { - /** - * In computer science, a list or sequence is an abstract data type that implements a - * finite ordered collection of values, where the same value may occur more than once. - * - * http://en.wikipedia.org/wiki/List_(abstract_data_type) - * - * @author Justin Wetherell - * - * @param list List to test. - * @param name Name used in debug. - * @param data Test data. - * @param invalid Invalid data which should not exist in the data. - * @return - */ public static > boolean testList(IList list, String name, T[] data, T _invalid) { for (int i = 0; i < data.length; i++) { diff --git a/test/com/jwetherell/algorithms/data_structures/test/common/MapTest.java b/test/com/jwetherell/algorithms/data_structures/test/common/MapTest.java index b1d12b62..41edd578 100644 --- a/test/com/jwetherell/algorithms/data_structures/test/common/MapTest.java +++ b/test/com/jwetherell/algorithms/data_structures/test/common/MapTest.java @@ -4,22 +4,6 @@ public class MapTest { - /** - * In computer science, an associative array, map, symbol table, or dictionary is an abstract data - * type composed of a collection of (key, value) pairs, such that each possible key appears at most - * once in the collection. - * - * http://en.wikipedia.org/wiki/Associative_array - * - * @author Justin Wetherell - * - * @param map Map to test. - * @param type Type of data in the map (Either String or Integer). - * @param name Name used in debug. - * @param data test data. - * @param invalid Invalid data which isn't in the data-structure. - * @return True if the map passes it's invariants tests. - */ @SuppressWarnings("unchecked") public static > boolean testMap(IMap map, Class type, String name, Integer[] data, Integer _invalid) { diff --git a/test/com/jwetherell/algorithms/data_structures/test/common/QueueTest.java b/test/com/jwetherell/algorithms/data_structures/test/common/QueueTest.java index 71990102..5bcef7f1 100644 --- a/test/com/jwetherell/algorithms/data_structures/test/common/QueueTest.java +++ b/test/com/jwetherell/algorithms/data_structures/test/common/QueueTest.java @@ -4,24 +4,6 @@ public class QueueTest { - /** - * In computer science, a queue is a particular kind of abstract data type or collection in which - * the entities in the collection are kept in order and the principal (or only) operations on the - * collection are the addition of entities to the rear terminal position, known as enqueue, and removal - * of entities from the front terminal position, known as dequeue. This makes the queue a First-In-First-Out - * (FIFO) data structure. In a FIFO data structure, the first element added to the queue will be the first - * one to be removed. - * - * http://en.wikipedia.org/wiki/Queue_(abstract_data_type) - * - * @author Justin Wetherell - * - * @param queue Queue to test. - * @param name Name used in debug. - * @param data Test data. - * @param invalid Invalid data which isn't in the data-structure. - * @return Trus if the Queue passes all it's invariants. - */ public static > boolean testQueue(IQueue queue, String name, T[] data, T _invalid) { for (int i = 0; i < data.length; i++) { diff --git a/test/com/jwetherell/algorithms/data_structures/test/common/SetTest.java b/test/com/jwetherell/algorithms/data_structures/test/common/SetTest.java index d64d371d..194e1a0e 100644 --- a/test/com/jwetherell/algorithms/data_structures/test/common/SetTest.java +++ b/test/com/jwetherell/algorithms/data_structures/test/common/SetTest.java @@ -4,20 +4,6 @@ public class SetTest { - /** - * In computer science, a set is an abstract data structure that can store certain values, - * without any particular order, and no repeated values. - * - * http://en.wikipedia.org/wiki/Set_(abstract_data_type) - * - * @author Justin Wetherell - * - * @param set Set to test. - * @param name Name to use in debug. - * @param data Test data. - * @param invalid Invalid data which isn't in the data-structure. - * @return True if the set passes it's invariants tests. - */ public static > boolean testSet(ISet set, String name, T[] data, T _invalid) { for (int i = 0; i < data.length; i++) { diff --git a/test/com/jwetherell/algorithms/data_structures/test/common/StackTest.java b/test/com/jwetherell/algorithms/data_structures/test/common/StackTest.java index 36f30c87..57554dba 100644 --- a/test/com/jwetherell/algorithms/data_structures/test/common/StackTest.java +++ b/test/com/jwetherell/algorithms/data_structures/test/common/StackTest.java @@ -4,21 +4,6 @@ public class StackTest { - /** - * In computer science, a stack is a particular kind of abstract data type or collection - * in which the principal (or only) operations on the collection are the addition of an - * entity to the collection, known as push and removal of an entity, known as pop. - * - * http://en.wikipedia.org/wiki/Stack_(abstract_data_type) - * - * @author Justin Wetherell - * - * @param stack Stack to test. - * @param name Name to use in debug. - * @param data Test data. - * @param invalid Invalid data which isn't in the data-structure. - * @return True if the stack passes it's invariants tests. - */ public static > boolean testStack(IStack stack, String name, T[] data, T _invalid) { for (int i = 0; i < data.length; i++) { diff --git a/test/com/jwetherell/algorithms/data_structures/test/common/TreeTest.java b/test/com/jwetherell/algorithms/data_structures/test/common/TreeTest.java index 5c4cef50..6df37169 100644 --- a/test/com/jwetherell/algorithms/data_structures/test/common/TreeTest.java +++ b/test/com/jwetherell/algorithms/data_structures/test/common/TreeTest.java @@ -4,22 +4,6 @@ public class TreeTest { - /** - * In computer science, a tree is a widely used abstract data type (ADT) or data structure implementing this ADT - * that simulates a hierarchical tree structure, with a root value and subtrees of children, represented as a set - * of linked nodes. - * - * http://en.wikipedia.org/wiki/Tree_(data_structure) - * - * @author Justin Wetherell - * - * @param tree Tree to test. - * @param type Type of data in the heap (Either String or Integer). - * @param name Name used in debug. - * @param data Test data. - * @param invalid Invalid data which isn't in the data-structure. - * @return True if the tree passes it's invariants tests. - */ public static > boolean testTree(ITree tree, Class type, String name, Integer[] data, Integer _invalid) { for (int i = 0; i < data.length; i++) { diff --git a/test/com/jwetherell/algorithms/graph/test/BreadthFirstTraversalTest.java b/test/com/jwetherell/algorithms/graph/test/BreadthFirstTraversalTest.java index 2fe88bcb..057ec566 100644 --- a/test/com/jwetherell/algorithms/graph/test/BreadthFirstTraversalTest.java +++ b/test/com/jwetherell/algorithms/graph/test/BreadthFirstTraversalTest.java @@ -12,6 +12,38 @@ public class BreadthFirstTraversalTest { + private static final byte[][] adjacencyMatrix = new byte[4][4]; + static { + // v0 + adjacencyMatrix[0][1] = 1; + adjacencyMatrix[0][2] = 1; + // v1 + adjacencyMatrix[1][2] = 1; + // v2 + adjacencyMatrix[2][0] = 1; + adjacencyMatrix[2][3] = 1; + // v3 + adjacencyMatrix[3][3] = 1; + } + + @Test + public void test0() { + final int[] result = BreadthFirstTraversal.breadthFirstTraversal(4, adjacencyMatrix, 2); + Assert.assertTrue(result[0]==2); + Assert.assertTrue(result[1]==0); + Assert.assertTrue(result[2]==3); + Assert.assertTrue(result[3]==1); + } + + @Test + public void test1() { + final int[] result = BreadthFirstTraversal.breadthFirstTraversal(4, adjacencyMatrix, 0); + Assert.assertTrue(result[0]==0); + Assert.assertTrue(result[1]==1); + Assert.assertTrue(result[2]==2); + Assert.assertTrue(result[3]==3); + } + private static final List> vertices = new ArrayList>(); private static final List> edges = new ArrayList>(); @@ -37,7 +69,7 @@ public class BreadthFirstTraversalTest { private static final Graph graph = new Graph(Graph.TYPE.DIRECTED, vertices, edges); @Test - public void test1() { + public void test2() { final Graph.Vertex[] result = BreadthFirstTraversal.breadthFirstTraversal(graph, v2); Assert.assertTrue(result[0].getValue()==2); Assert.assertTrue(result[1].getValue()==0); @@ -46,7 +78,7 @@ public void test1() { } @Test - public void test2() { + public void test3() { final Graph.Vertex[] result = BreadthFirstTraversal.breadthFirstTraversal(graph, v0); Assert.assertTrue(result[0].getValue()==0); Assert.assertTrue(result[1].getValue()==1); diff --git a/test/com/jwetherell/algorithms/graph/test/DepthFirstTraversalTest.java b/test/com/jwetherell/algorithms/graph/test/DepthFirstTraversalTest.java new file mode 100644 index 00000000..48e26c89 --- /dev/null +++ b/test/com/jwetherell/algorithms/graph/test/DepthFirstTraversalTest.java @@ -0,0 +1,89 @@ +package com.jwetherell.algorithms.graph.test; + +import java.util.ArrayList; +import java.util.List; + +import junit.framework.Assert; + +import org.junit.Test; + +import com.jwetherell.algorithms.data_structures.Graph; +import com.jwetherell.algorithms.graph.DepthFirstTraversal; + +public class DepthFirstTraversalTest { + + private static final byte[][] adjacencyMatrix = new byte[4][4]; + static { + // v0 + adjacencyMatrix[0][1] = 1; + adjacencyMatrix[0][2] = 1; + // v1 + adjacencyMatrix[1][2] = 1; + // v2 + adjacencyMatrix[2][0] = 1; + adjacencyMatrix[2][3] = 1; + // v3 + adjacencyMatrix[3][3] = 1; + } + + @Test + public void test0() { + final int[] result = DepthFirstTraversal.depthFirstTraversal(4, adjacencyMatrix, 2); + Assert.assertTrue(result[0]==2); + Assert.assertTrue(result[1]==0); + Assert.assertTrue(result[2]==1); + Assert.assertTrue(result[3]==3); + } + + @Test + public void test1() { + final int[] result = DepthFirstTraversal.depthFirstTraversal(4, adjacencyMatrix, 0); + Assert.assertTrue(result[0]==0); + Assert.assertTrue(result[1]==1); + Assert.assertTrue(result[2]==2); + Assert.assertTrue(result[3]==3); + } + + private static final List> vertices = new ArrayList>(); + private static final List> edges = new ArrayList>(); + + private static final Graph.Vertex v0 = new Graph.Vertex(0); + private static final Graph.Vertex v1 = new Graph.Vertex(1); + private static final Graph.Vertex v2 = new Graph.Vertex(2); + private static final Graph.Vertex v3 = new Graph.Vertex(3); + + static { + vertices.add(v0); + vertices.add(v1); + vertices.add(v2); + vertices.add(v3); + + edges.add(new Graph.Edge(0, v0, v1)); + edges.add(new Graph.Edge(0, v0, v2)); + edges.add(new Graph.Edge(0, v1, v2)); + edges.add(new Graph.Edge(0, v2, v0)); + edges.add(new Graph.Edge(0, v2, v3)); + edges.add(new Graph.Edge(0, v3, v3)); + } + + private static final Graph graph = new Graph(Graph.TYPE.DIRECTED, vertices, edges); + + @Test + public void test2() { + final Graph.Vertex[] result = DepthFirstTraversal.depthFirstTraversal(graph, v2); + Assert.assertTrue(result[0].getValue()==2); + Assert.assertTrue(result[1].getValue()==0); + Assert.assertTrue(result[2].getValue()==1); + Assert.assertTrue(result[3].getValue()==3); + } + + @Test + public void test3() { + final Graph.Vertex[] result = DepthFirstTraversal.depthFirstTraversal(graph, v0); + Assert.assertTrue(result[0].getValue()==0); + Assert.assertTrue(result[1].getValue()==1); + Assert.assertTrue(result[2].getValue()==2); + Assert.assertTrue(result[3].getValue()==3); + } +} + From 330c3264f51045b8004664d0239a8ac05368249a Mon Sep 17 00:00:00 2001 From: Lucjan Roslanowski Date: Tue, 4 Jul 2017 00:57:56 +0200 Subject: [PATCH 32/88] adding discrete logarithm --- .../mathematics/DiscreteLogarithm.java | 65 +++++++++++++++++++ .../mathematics/DiscreteLogarithmTest.java | 53 +++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 src/com/jwetherell/algorithms/mathematics/DiscreteLogarithm.java create mode 100644 test/com/jwetherell/algorithms/mathematics/DiscreteLogarithmTest.java diff --git a/src/com/jwetherell/algorithms/mathematics/DiscreteLogarithm.java b/src/com/jwetherell/algorithms/mathematics/DiscreteLogarithm.java new file mode 100644 index 00000000..11f7f4b6 --- /dev/null +++ b/src/com/jwetherell/algorithms/mathematics/DiscreteLogarithm.java @@ -0,0 +1,65 @@ +package com.jwetherell.algorithms.mathematics; + +import java.util.HashMap; + +import static java.lang.Math.sqrt; + +/** + * https://en.wikipedia.org/wiki/Discrete_logarithm + * a^x = b mod p + * x = ? + *
+ * Created on 03.07.2017. + * + * @author lucjanroslanowski + */ +public class DiscreteLogarithm { + private static long NO_SOLUTION = -1; + private HashMap set = new HashMap<>(); + + private long pow(long a, long x, long p) { + if (x == 0) { + return 1; + } + + if (x == 1) { + return a % p; + } + + if (x % 2 != 0) { + return (a * pow(a, x - 1, p)) % p; + } else { + long temp = pow(a, x / 2, p) % p; + return (temp * temp) % p; + } + } + + + private long getDiscreteLogarithm(long s, long a, long p) { + for (long i = 0; i < s; ++i) { + long el = pow(a, (i * s) % p, p); + el = pow(el, p - 2, p); + + if (set.containsKey(el)) { + return i * s + set.get(el); + } + } + return NO_SOLUTION; + } + + private void generateSet(long a, long b_1, long p, long s) { + for (long i = 0; i < s; ++i) { + long first = (pow(a, i, p) * b_1) % p; + if (!set.containsKey(first)) { + set.put(first, i); + } + } + } + + public long countDiscreteLogarithm(final long a, final long b, final long p) { + long s = (long) sqrt(p) + 1; + long b_1 = pow(b, p - 2, p); + generateSet(a, b_1, p, s); + return getDiscreteLogarithm(s,a,p); + } +} \ No newline at end of file diff --git a/test/com/jwetherell/algorithms/mathematics/DiscreteLogarithmTest.java b/test/com/jwetherell/algorithms/mathematics/DiscreteLogarithmTest.java new file mode 100644 index 00000000..066b18ae --- /dev/null +++ b/test/com/jwetherell/algorithms/mathematics/DiscreteLogarithmTest.java @@ -0,0 +1,53 @@ +package com.jwetherell.algorithms.mathematics; + +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +/** + *
+ * Created on 04.07.2017. + * + * @author lucjanroslanowski + */ +public class DiscreteLogarithmTest { + + @Test + public void shouldCountDiscreteLogarithm() { + final DiscreteLogarithm discreteLogarithm = new DiscreteLogarithm(); + final long a = 3; + final long b = 4; + final long p = 7; + final long expectedX = 4; + + long x = discreteLogarithm.countDiscreteLogarithm(a, b, p); + + assertTrue(x == expectedX); + } + + @Test + public void shouldCountDiscreteLogarithm2() { + final DiscreteLogarithm discreteLogarithm = new DiscreteLogarithm(); + final long a = 2; + final long b = 64; + final long p = 101; + final long expectedX = 6; + + long x = discreteLogarithm.countDiscreteLogarithm(a, b, p); + + assertTrue(x == expectedX); + } + + @Test + public void shouldNotCountDiscreteLogarithm() { + final DiscreteLogarithm discreteLogarithm = new DiscreteLogarithm(); + final long a = 4; + final long b = 5; + final long p = 7; + final long expectedX = -1; + + long x = discreteLogarithm.countDiscreteLogarithm(a, b, p); + + assertTrue(x == expectedX); + } +} \ No newline at end of file From 13d477320e3b19ae3c53d849dca87f263ff3b16e Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Mon, 3 Jul 2017 19:16:29 -0400 Subject: [PATCH 33/88] Code clean-up --- .../mathematics/DiscreteLogarithm.java | 55 ++++++++++--------- .../{ => test}/DiscreteLogarithmTest.java | 10 +--- 2 files changed, 32 insertions(+), 33 deletions(-) rename test/com/jwetherell/algorithms/mathematics/{ => test}/DiscreteLogarithmTest.java (90%) diff --git a/src/com/jwetherell/algorithms/mathematics/DiscreteLogarithm.java b/src/com/jwetherell/algorithms/mathematics/DiscreteLogarithm.java index 11f7f4b6..17ef2e3e 100644 --- a/src/com/jwetherell/algorithms/mathematics/DiscreteLogarithm.java +++ b/src/com/jwetherell/algorithms/mathematics/DiscreteLogarithm.java @@ -5,61 +5,64 @@ import static java.lang.Math.sqrt; /** - * https://en.wikipedia.org/wiki/Discrete_logarithm - * a^x = b mod p - * x = ? + * In mathematics, a discrete logarithm is an integer k exponent solving the equation bk = g, where b and g are + * elements of a group. Discrete logarithms are thus the group-theoretic analogue of ordinary logarithms, which + * solve the same equation for real numbers b and g, where b is the base of the logarithm and g is the value whose + * logarithm is being taken. + *

+ * @see Discrete Logarithm (Wikipedia) *
- * Created on 03.07.2017. - * - * @author lucjanroslanowski + * @author Lucjan Rosłanowski + * @author Justin Wetherell */ public class DiscreteLogarithm { - private static long NO_SOLUTION = -1; - private HashMap set = new HashMap<>(); + + public static final long NO_SOLUTION = -1; + + private final HashMap set = new HashMap(); private long pow(long a, long x, long p) { - if (x == 0) { + if (x == 0) return 1; - } - if (x == 1) { + if (x == 1) return a % p; - } - if (x % 2 != 0) { + if (x % 2 != 0) return (a * pow(a, x - 1, p)) % p; - } else { - long temp = pow(a, x / 2, p) % p; - return (temp * temp) % p; - } - } + final long temp = pow(a, x / 2, p) % p; + return (temp * temp) % p; + } private long getDiscreteLogarithm(long s, long a, long p) { for (long i = 0; i < s; ++i) { long el = pow(a, (i * s) % p, p); el = pow(el, p - 2, p); - if (set.containsKey(el)) { + if (set.containsKey(el)) return i * s + set.get(el); - } } return NO_SOLUTION; } private void generateSet(long a, long b_1, long p, long s) { for (long i = 0; i < s; ++i) { - long first = (pow(a, i, p) * b_1) % p; - if (!set.containsKey(first)) { + final long first = (pow(a, i, p) * b_1) % p; + if (!set.containsKey(first)) set.put(first, i); - } } } + /** + * Returns DiscreteLogarithm.NO_SOLUTION when a solution cannot be found + */ public long countDiscreteLogarithm(final long a, final long b, final long p) { - long s = (long) sqrt(p) + 1; - long b_1 = pow(b, p - 2, p); + final long s = (long) sqrt(p) + 1; + final long b_1 = pow(b, p - 2, p); + set.clear(); + generateSet(a, b_1, p, s); return getDiscreteLogarithm(s,a,p); } -} \ No newline at end of file +} diff --git a/test/com/jwetherell/algorithms/mathematics/DiscreteLogarithmTest.java b/test/com/jwetherell/algorithms/mathematics/test/DiscreteLogarithmTest.java similarity index 90% rename from test/com/jwetherell/algorithms/mathematics/DiscreteLogarithmTest.java rename to test/com/jwetherell/algorithms/mathematics/test/DiscreteLogarithmTest.java index 066b18ae..7b325a5d 100644 --- a/test/com/jwetherell/algorithms/mathematics/DiscreteLogarithmTest.java +++ b/test/com/jwetherell/algorithms/mathematics/test/DiscreteLogarithmTest.java @@ -1,15 +1,11 @@ -package com.jwetherell.algorithms.mathematics; +package com.jwetherell.algorithms.mathematics.test; import org.junit.Test; +import com.jwetherell.algorithms.mathematics.DiscreteLogarithm; + import static org.junit.Assert.assertTrue; -/** - *
- * Created on 04.07.2017. - * - * @author lucjanroslanowski - */ public class DiscreteLogarithmTest { @Test From 4c167b1f4c3c1906724e473323b88c45122b852d Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Mon, 3 Jul 2017 20:46:14 -0400 Subject: [PATCH 34/88] Code clean-up --- .../mathematics/DiscreteLogarithm.java | 18 ++++++++++-------- .../test/DiscreteLogarithmTest.java | 12 +++--------- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/src/com/jwetherell/algorithms/mathematics/DiscreteLogarithm.java b/src/com/jwetherell/algorithms/mathematics/DiscreteLogarithm.java index 17ef2e3e..f3d470d6 100644 --- a/src/com/jwetherell/algorithms/mathematics/DiscreteLogarithm.java +++ b/src/com/jwetherell/algorithms/mathematics/DiscreteLogarithm.java @@ -19,9 +19,11 @@ public class DiscreteLogarithm { public static final long NO_SOLUTION = -1; - private final HashMap set = new HashMap(); + private static final HashMap set = new HashMap(); - private long pow(long a, long x, long p) { + private DiscreteLogarithm() { } + + private static final long pow(long a, long x, long p) { if (x == 0) return 1; @@ -35,7 +37,7 @@ private long pow(long a, long x, long p) { return (temp * temp) % p; } - private long getDiscreteLogarithm(long s, long a, long p) { + private static final long getDiscreteLogarithm(HashMap set, long s, long a, long p) { for (long i = 0; i < s; ++i) { long el = pow(a, (i * s) % p, p); el = pow(el, p - 2, p); @@ -46,7 +48,8 @@ private long getDiscreteLogarithm(long s, long a, long p) { return NO_SOLUTION; } - private void generateSet(long a, long b_1, long p, long s) { + private static final void generateSet(long a, long b_1, long p, long s, HashMap set) { + set.clear(); for (long i = 0; i < s; ++i) { final long first = (pow(a, i, p) * b_1) % p; if (!set.containsKey(first)) @@ -57,12 +60,11 @@ private void generateSet(long a, long b_1, long p, long s) { /** * Returns DiscreteLogarithm.NO_SOLUTION when a solution cannot be found */ - public long countDiscreteLogarithm(final long a, final long b, final long p) { + public static final long countDiscreteLogarithm(final long a, final long b, final long p) { final long s = (long) sqrt(p) + 1; final long b_1 = pow(b, p - 2, p); - set.clear(); - generateSet(a, b_1, p, s); - return getDiscreteLogarithm(s,a,p); + generateSet(a, b_1, p, s, set); + return getDiscreteLogarithm(set, s,a,p); } } diff --git a/test/com/jwetherell/algorithms/mathematics/test/DiscreteLogarithmTest.java b/test/com/jwetherell/algorithms/mathematics/test/DiscreteLogarithmTest.java index 7b325a5d..a30168ff 100644 --- a/test/com/jwetherell/algorithms/mathematics/test/DiscreteLogarithmTest.java +++ b/test/com/jwetherell/algorithms/mathematics/test/DiscreteLogarithmTest.java @@ -10,40 +10,34 @@ public class DiscreteLogarithmTest { @Test public void shouldCountDiscreteLogarithm() { - final DiscreteLogarithm discreteLogarithm = new DiscreteLogarithm(); final long a = 3; final long b = 4; final long p = 7; final long expectedX = 4; - long x = discreteLogarithm.countDiscreteLogarithm(a, b, p); - + final long x = DiscreteLogarithm.countDiscreteLogarithm(a, b, p); assertTrue(x == expectedX); } @Test public void shouldCountDiscreteLogarithm2() { - final DiscreteLogarithm discreteLogarithm = new DiscreteLogarithm(); final long a = 2; final long b = 64; final long p = 101; final long expectedX = 6; - long x = discreteLogarithm.countDiscreteLogarithm(a, b, p); - + final long x = DiscreteLogarithm.countDiscreteLogarithm(a, b, p); assertTrue(x == expectedX); } @Test public void shouldNotCountDiscreteLogarithm() { - final DiscreteLogarithm discreteLogarithm = new DiscreteLogarithm(); final long a = 4; final long b = 5; final long p = 7; final long expectedX = -1; - long x = discreteLogarithm.countDiscreteLogarithm(a, b, p); - + final long x = DiscreteLogarithm.countDiscreteLogarithm(a, b, p); assertTrue(x == expectedX); } } \ No newline at end of file From 6901b22a451a5bd9601501293390509f2906e6f5 Mon Sep 17 00:00:00 2001 From: mciancia Date: Tue, 4 Jul 2017 17:42:51 +0200 Subject: [PATCH 35/88] Adds LU decomposition algorithm --- .../algorithms/data_structures/Matrix.java | 188 +++++++++--------- .../mathematics/LUDecomposition.java | 95 +++++++++ .../mathematics/test/LUDecompositionTest.java | 46 +++++ 3 files changed, 239 insertions(+), 90 deletions(-) create mode 100644 src/com/jwetherell/algorithms/mathematics/LUDecomposition.java create mode 100644 test/com/jwetherell/algorithms/mathematics/test/LUDecompositionTest.java diff --git a/src/com/jwetherell/algorithms/data_structures/Matrix.java b/src/com/jwetherell/algorithms/data_structures/Matrix.java index 717b757c..73de83a6 100644 --- a/src/com/jwetherell/algorithms/data_structures/Matrix.java +++ b/src/com/jwetherell/algorithms/data_structures/Matrix.java @@ -5,11 +5,11 @@ import java.util.Comparator; /** - * Matrx. This Matrix implementation is designed to be more efficient + * Matrx. This Matrix implementation is designed to be more efficient * in cache. A matrix is a rectangular array of numbers, symbols, or expressions. - * + *

* http://en.wikipedia.org/wiki/Matrix_(mathematics) - * + * * @author Justin Wetherell */ @SuppressWarnings("unchecked") @@ -28,28 +28,28 @@ public int compare(T o1, T o2) { /* TODO: What if Java adds new numeric type? */ int result = 0; if (o1 instanceof BigDecimal || o2 instanceof BigDecimal) { - BigDecimal c1 = (BigDecimal)o1; - BigDecimal c2 = (BigDecimal)o2; + BigDecimal c1 = (BigDecimal) o1; + BigDecimal c2 = (BigDecimal) o2; result = c1.compareTo(c2); } else if (o1 instanceof BigInteger || o2 instanceof BigInteger) { - BigInteger c1 = (BigInteger)o1; - BigInteger c2 = (BigInteger)o2; + BigInteger c1 = (BigInteger) o1; + BigInteger c2 = (BigInteger) o2; result = c1.compareTo(c2); } else if (o1 instanceof Long || o2 instanceof Long) { Long c1 = o1.longValue(); - Long c2 = o2.longValue(); + Long c2 = o2.longValue(); result = c1.compareTo(c2); } else if (o1 instanceof Double || o2 instanceof Double) { Double c1 = o1.doubleValue(); - Double c2 = o2.doubleValue(); - result = c1.compareTo(c2); + Double c2 = o2.doubleValue(); + result = c1.compareTo(c2); } else if (o1 instanceof Float || o2 instanceof Float) { Float c1 = o1.floatValue(); - Float c2 = o2.floatValue(); - result = c1.compareTo(c2); + Float c2 = o2.floatValue(); + result = c1.compareTo(c2); } else { Integer c1 = o1.intValue(); - Integer c2 = o2.intValue(); + Integer c2 = o2.intValue(); result = c1.compareTo(c2); } return result; @@ -58,7 +58,7 @@ public int compare(T o1, T o2) { /** * Matrix with 'rows' number of rows and 'cols' number of columns. - * + * * @param rows Number of rows in Matrix. * @param cols Number of columns in Matrix. */ @@ -71,18 +71,18 @@ public Matrix(int rows, int cols) { /** * Matrix with 'rows' number of rows and 'cols' number of columns, populates * the double index matrix. - * - * @param rows Number of rows in Matrix. - * @param cols Number of columns in Matrix. + * + * @param rows Number of rows in Matrix. + * @param cols Number of columns in Matrix. * @param matrix 2D matrix used to populate Matrix. */ public Matrix(int rows, int cols, T[][] matrix) { this.rows = rows; this.cols = cols; this.matrix = (T[]) new Number[rows * cols]; - for (int r=0; r identity() throws Exception{ - if(this.rows != this.cols) - throw new Exception("Matrix should be a square"); + public Matrix identity() throws Exception { + if (this.rows != this.cols) + throw new Exception("Matrix should be a square"); final T element = this.get(0, 0); final T zero; final T one; - if (element instanceof BigDecimal) { - zero = (T)BigDecimal.ZERO; - one = (T)BigDecimal.ONE; - } else if(element instanceof BigInteger){ - zero = (T)BigInteger.ZERO; - one = (T)BigInteger.ONE; - } else if(element instanceof Long){ - zero = (T)new Long(0); - one = (T)new Long(1); - } else if(element instanceof Double){ - zero = (T)new Double(0); - one = (T)new Double(1); - } else if(element instanceof Float){ - zero = (T)new Float(0); - one = (T)new Float(1); + if (element instanceof BigDecimal) { + zero = (T) BigDecimal.ZERO; + one = (T) BigDecimal.ONE; + } else if (element instanceof BigInteger) { + zero = (T) BigInteger.ZERO; + one = (T) BigInteger.ONE; + } else if (element instanceof Long) { + zero = (T) new Long(0); + one = (T) new Long(1); + } else if (element instanceof Double) { + zero = (T) new Double(0); + one = (T) new Double(1); + } else if (element instanceof Float) { + zero = (T) new Float(0); + one = (T) new Float(1); } else { - zero = (T)new Integer(0); - one = (T)new Integer(1); + zero = (T) new Integer(0); + one = (T) new Integer(1); + } + + final T array[][] = (T[][]) new Number[this.rows][this.cols]; + for (int i = 0; i < this.rows; ++i) { + for (int j = 0; j < this.cols; ++j) { + array[i][j] = zero; + } } - final T array[][] = (T[][])new Number[this.rows][this.cols]; - for(int i = 0; i < this.rows; ++i) { - for(int j = 0 ; j < this.cols; ++j){ - array[i][j] = zero; - } - } - - final Matrix identityMatrix = new Matrix(this.rows, this.cols, array); - for(int i = 0; i < this.rows;++i){ - identityMatrix.set(i, i, one); - } - return identityMatrix; + final Matrix identityMatrix = new Matrix(this.rows, this.cols, array); + for (int i = 0; i < this.rows; ++i) { + identityMatrix.set(i, i, one); + } + return identityMatrix; } - + public Matrix add(Matrix input) { Matrix output = new Matrix(this.rows, this.cols); if ((this.cols != input.cols) || (this.rows != input.rows)) @@ -168,24 +168,24 @@ public Matrix add(Matrix input) { T result; /* TODO: This is ugly and how to handle number overflow? */ if (m1 instanceof BigDecimal || m2 instanceof BigDecimal) { - BigDecimal result2 = ((BigDecimal)m1).add((BigDecimal)m2); - result = (T)result2; + BigDecimal result2 = ((BigDecimal) m1).add((BigDecimal) m2); + result = (T) result2; } else if (m1 instanceof BigInteger || m2 instanceof BigInteger) { - BigInteger result2 = ((BigInteger)m1).add((BigInteger)m2); - result = (T)result2; + BigInteger result2 = ((BigInteger) m1).add((BigInteger) m2); + result = (T) result2; } else if (m1 instanceof Long || m2 instanceof Long) { Long result2 = (m1.longValue() + m2.longValue()); - result = (T)result2; + result = (T) result2; } else if (m1 instanceof Double || m2 instanceof Double) { Double result2 = (m1.doubleValue() + m2.doubleValue()); - result = (T)result2; + result = (T) result2; } else if (m1 instanceof Float || m2 instanceof Float) { Float result2 = (m1.floatValue() + m2.floatValue()); - result = (T)result2; + result = (T) result2; } else { // Integer Integer result2 = (m1.intValue() + m2.intValue()); - result = (T)result2; + result = (T) result2; } output.set(r, c, result); } @@ -207,24 +207,24 @@ public Matrix subtract(Matrix input) { T result; /* TODO: This is ugly and how to handle number overflow? */ if (m1 instanceof BigDecimal || m2 instanceof BigDecimal) { - BigDecimal result2 = ((BigDecimal)m1).subtract((BigDecimal)m2); - result = (T)result2; + BigDecimal result2 = ((BigDecimal) m1).subtract((BigDecimal) m2); + result = (T) result2; } else if (m1 instanceof BigInteger || m2 instanceof BigInteger) { - BigInteger result2 = ((BigInteger)m1).subtract((BigInteger)m2); - result = (T)result2; + BigInteger result2 = ((BigInteger) m1).subtract((BigInteger) m2); + result = (T) result2; } else if (m1 instanceof Long || m2 instanceof Long) { Long result2 = (m1.longValue() - m2.longValue()); - result = (T)result2; + result = (T) result2; } else if (m1 instanceof Double || m2 instanceof Double) { Double result2 = (m1.doubleValue() - m2.doubleValue()); - result = (T)result2; + result = (T) result2; } else if (m1 instanceof Float || m2 instanceof Float) { Float result2 = (m1.floatValue() - m2.floatValue()); - result = (T)result2; + result = (T) result2; } else { // Integer Integer result2 = (m1.intValue() - m2.intValue()); - result = (T)result2; + result = (T) result2; } output.set(r, c, result); } @@ -249,62 +249,62 @@ public Matrix multiply(Matrix input) { for (int i = 0; i < cols; i++) { T m1 = row[i]; T m2 = column[i]; - - BigDecimal result2 = ((BigDecimal)m1).multiply(((BigDecimal)m2)); + + BigDecimal result2 = ((BigDecimal) m1).multiply(((BigDecimal) m2)); result = result.add(result2); } - output.set(r, c, (T)result); + output.set(r, c, (T) result); } else if (test instanceof BigInteger) { BigInteger result = BigInteger.ZERO; for (int i = 0; i < cols; i++) { T m1 = row[i]; T m2 = column[i]; - - BigInteger result2 = ((BigInteger)m1).multiply(((BigInteger)m2)); + + BigInteger result2 = ((BigInteger) m1).multiply(((BigInteger) m2)); result = result.add(result2); } - output.set(r, c, (T)result); + output.set(r, c, (T) result); } else if (test instanceof Long) { Long result = 0l; for (int i = 0; i < cols; i++) { T m1 = row[i]; T m2 = column[i]; - + Long result2 = m1.longValue() * m2.longValue(); - result = result+result2; + result = result + result2; } - output.set(r, c, (T)result); + output.set(r, c, (T) result); } else if (test instanceof Double) { Double result = 0d; for (int i = 0; i < cols; i++) { T m1 = row[i]; T m2 = column[i]; - + Double result2 = m1.doubleValue() * m2.doubleValue(); - result = result+result2; + result = result + result2; } - output.set(r, c, (T)result); + output.set(r, c, (T) result); } else if (test instanceof Float) { Float result = 0f; for (int i = 0; i < cols; i++) { T m1 = row[i]; T m2 = column[i]; - + Float result2 = m1.floatValue() * m2.floatValue(); - result = result+result2; + result = result + result2; } - output.set(r, c, (T)result); + output.set(r, c, (T) result); } else { // Integer Integer result = 0; for (int i = 0; i < cols; i++) { T m1 = row[i]; T m2 = column[i]; - + Integer result2 = m1.intValue() * m2.intValue(); - result = result+result2; + result = result + result2; } - output.set(r, c, (T)result); + output.set(r, c, (T) result); } } } @@ -345,11 +345,11 @@ public boolean equals(Object obj) { return false; if (this.cols != m.cols) return false; - for (int i=0; i + * https://en.wikipedia.org/wiki/LU_decomposition + *
+ * @author Mateusz Cianciara + */ +public class LUDecomposition { + private Double[][] L = null; + private Double[][] A = null; + private Integer[] permutation = null; + private int n = 0; + + public Matrix getL() { + return new Matrix(n, n, L); + } + + public Matrix getU() { + return new Matrix(n, n, A); + } + + public List getPermutation() { + return new ArrayList<>(Arrays.asList(permutation)); + } + + public LUDecomposition(Matrix input) { + if (input.getCols() != input.getRows()) { + throw new IllegalArgumentException("Matrix is not square"); + } + n = input.getCols(); + L = new Double[n][n]; + A = new Double[n][n]; + permutation = new Integer[n]; + + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + L[i][j] = 0.0; + A[i][j] = input.get(i, j); + } + } + for (int i = 0; i < n; i++) { + L[i][i] = 1.0; + permutation[i] = i; + } + for (int row = 0; row < n; row++) { + // find max in column + int max_in_col = row; + double curr_big = Math.abs(A[row][row]); + for (int k = row + 1; k < n; k++) { + if (curr_big < Math.abs(A[k][row])) { + max_in_col = k; + curr_big = Math.abs(A[k][row]); + } + } + + //swap rows + if (row != max_in_col) { + for (int i = 0; i < n; i++) { + double temp = A[row][i]; + A[row][i] = A[max_in_col][i]; + A[max_in_col][i] = temp; + if (i < row) { + temp = L[row][i]; + L[row][i] = L[max_in_col][i]; + L[max_in_col][i] = temp; + } + } + int temp = permutation[row]; + permutation[row] = permutation[max_in_col]; + permutation[max_in_col] = temp; + } + //zero column number row + double p = A[row][row]; + if (p == 0) return; + + for (int i = row + 1; i < n; i++) { + double y = A[i][row]; + L[i][row] = y / p; + + for (int j = row; j < n; j++) { + A[i][j] -= A[row][j] * (y / p); + } + } + } + } +} diff --git a/test/com/jwetherell/algorithms/mathematics/test/LUDecompositionTest.java b/test/com/jwetherell/algorithms/mathematics/test/LUDecompositionTest.java new file mode 100644 index 00000000..cd5d0246 --- /dev/null +++ b/test/com/jwetherell/algorithms/mathematics/test/LUDecompositionTest.java @@ -0,0 +1,46 @@ +package com.jwetherell.algorithms.mathematics.test; + +import com.jwetherell.algorithms.data_structures.Matrix; +import com.jwetherell.algorithms.mathematics.LUDecomposition; +import org.junit.Test; + +import static org.junit.Assert.*; + + +public class LUDecompositionTest { + private boolean epsiMatrixCompare(Matrix a, Matrix b, double epsi) { + if (a.getRows() != b.getRows() || a.getCols() != b.getCols()) { + throw new IllegalArgumentException("Matrices are not the same shape"); + } + for (int i = 0; i < a.getRows(); i++) { + for (int j = 0; j < a.getCols(); j++) { + if (Math.abs(a.get(i, j) - b.get(i, j)) > epsi) { + return false; + } + } + } + return true; + } + + @Test + public void decompositionTest1() throws Exception { + Double[][] m = new Double[][]{{4.0, 3.0}, {6.0, 3.0}}; + Double[][] resultL = new Double[][]{{1.0, 0.0}, {2.0 / 3.0, 1.0}}; + Double[][] resultU = new Double[][]{{6.0, 3.0}, {0.0, 1.0}}; + + LUDecomposition luDecomposition = new LUDecomposition(new Matrix(2, 2, m)); + assertTrue(epsiMatrixCompare(luDecomposition.getL(), new Matrix(2, 2, resultL), 10e-4)); + assertTrue(epsiMatrixCompare(luDecomposition.getU(), new Matrix(2, 2, resultU), 10e-4)); + } + + @Test + public void decompositionTest2() throws Exception { + Double[][] m = new Double[][]{{5.0, 3.0, 2.0}, {1.0, 2.0, 0.0}, {3.0, 0.0, 4.0}}; + Double[][] resultL = new Double[][]{{1.0, 0.0, 0.0}, {0.6, 1.0, 0.0}, {0.2, -0.7778, 1.0}}; + Double[][] resultU = new Double[][]{{5.0, 3.0, 2.0}, {0.0, -1.8, 2.8}, {0.0, 0.0, 1.778}}; + + LUDecomposition luDecomposition = new LUDecomposition(new Matrix(3, 3, m)); + assertTrue(epsiMatrixCompare(luDecomposition.getL(), new Matrix(3, 3, resultL), 10e-4)); + assertTrue(epsiMatrixCompare(luDecomposition.getU(), new Matrix(3, 3, resultU), 10e-4)); + } +} \ No newline at end of file From f355ec5aaee93587625cd0c24382132e9e6a455d Mon Sep 17 00:00:00 2001 From: mciancia Date: Tue, 4 Jul 2017 20:41:41 +0200 Subject: [PATCH 36/88] Fixed compatibility with java 1.6 --- .../algorithms/data_structures/Matrix.java | 128 +++++++++--------- .../mathematics/LUDecomposition.java | 2 +- 2 files changed, 65 insertions(+), 65 deletions(-) diff --git a/src/com/jwetherell/algorithms/data_structures/Matrix.java b/src/com/jwetherell/algorithms/data_structures/Matrix.java index 73de83a6..0d814e18 100644 --- a/src/com/jwetherell/algorithms/data_structures/Matrix.java +++ b/src/com/jwetherell/algorithms/data_structures/Matrix.java @@ -8,8 +8,8 @@ * Matrx. This Matrix implementation is designed to be more efficient * in cache. A matrix is a rectangular array of numbers, symbols, or expressions. *

- * http://en.wikipedia.org/wiki/Matrix_(mathematics) - * + * @see Matrix (Wikipedia) + *
* @author Justin Wetherell */ @SuppressWarnings("unchecked") @@ -28,12 +28,12 @@ public int compare(T o1, T o2) { /* TODO: What if Java adds new numeric type? */ int result = 0; if (o1 instanceof BigDecimal || o2 instanceof BigDecimal) { - BigDecimal c1 = (BigDecimal) o1; - BigDecimal c2 = (BigDecimal) o2; + BigDecimal c1 = (BigDecimal)o1; + BigDecimal c2 = (BigDecimal)o2; result = c1.compareTo(c2); } else if (o1 instanceof BigInteger || o2 instanceof BigInteger) { - BigInteger c1 = (BigInteger) o1; - BigInteger c2 = (BigInteger) o2; + BigInteger c1 = (BigInteger)o1; + BigInteger c2 = (BigInteger)o2; result = c1.compareTo(c2); } else if (o1 instanceof Long || o2 instanceof Long) { Long c1 = o1.longValue(); @@ -72,17 +72,17 @@ public Matrix(int rows, int cols) { * Matrix with 'rows' number of rows and 'cols' number of columns, populates * the double index matrix. * - * @param rows Number of rows in Matrix. - * @param cols Number of columns in Matrix. + * @param rows Number of rows in Matrix. + * @param cols Number of columns in Matrix. * @param matrix 2D matrix used to populate Matrix. */ public Matrix(int rows, int cols, T[][] matrix) { this.rows = rows; this.cols = cols; this.matrix = (T[]) new Number[rows * cols]; - for (int r = 0; r < rows; r++) - for (int c = 0; c < cols; c++) - this.matrix[getIndex(r, c)] = matrix[r][c]; + for (int r=0; r identity() throws Exception { - if (this.rows != this.cols) + public Matrix identity() throws Exception{ + if(this.rows != this.cols) throw new Exception("Matrix should be a square"); final T element = this.get(0, 0); final T zero; final T one; if (element instanceof BigDecimal) { - zero = (T) BigDecimal.ZERO; - one = (T) BigDecimal.ONE; - } else if (element instanceof BigInteger) { - zero = (T) BigInteger.ZERO; - one = (T) BigInteger.ONE; - } else if (element instanceof Long) { - zero = (T) new Long(0); - one = (T) new Long(1); - } else if (element instanceof Double) { - zero = (T) new Double(0); - one = (T) new Double(1); - } else if (element instanceof Float) { - zero = (T) new Float(0); - one = (T) new Float(1); + zero = (T)BigDecimal.ZERO; + one = (T)BigDecimal.ONE; + } else if(element instanceof BigInteger){ + zero = (T)BigInteger.ZERO; + one = (T)BigInteger.ONE; + } else if(element instanceof Long){ + zero = (T)new Long(0); + one = (T)new Long(1); + } else if(element instanceof Double){ + zero = (T)new Double(0); + one = (T)new Double(1); + } else if(element instanceof Float){ + zero = (T)new Float(0); + one = (T)new Float(1); } else { - zero = (T) new Integer(0); - one = (T) new Integer(1); + zero = (T)new Integer(0); + one = (T)new Integer(1); } - final T array[][] = (T[][]) new Number[this.rows][this.cols]; - for (int i = 0; i < this.rows; ++i) { - for (int j = 0; j < this.cols; ++j) { + final T array[][] = (T[][])new Number[this.rows][this.cols]; + for(int i = 0; i < this.rows; ++i) { + for(int j = 0 ; j < this.cols; ++j){ array[i][j] = zero; } } final Matrix identityMatrix = new Matrix(this.rows, this.cols, array); - for (int i = 0; i < this.rows; ++i) { + for(int i = 0; i < this.rows;++i){ identityMatrix.set(i, i, one); } return identityMatrix; @@ -168,24 +168,24 @@ public Matrix add(Matrix input) { T result; /* TODO: This is ugly and how to handle number overflow? */ if (m1 instanceof BigDecimal || m2 instanceof BigDecimal) { - BigDecimal result2 = ((BigDecimal) m1).add((BigDecimal) m2); - result = (T) result2; + BigDecimal result2 = ((BigDecimal)m1).add((BigDecimal)m2); + result = (T)result2; } else if (m1 instanceof BigInteger || m2 instanceof BigInteger) { - BigInteger result2 = ((BigInteger) m1).add((BigInteger) m2); - result = (T) result2; + BigInteger result2 = ((BigInteger)m1).add((BigInteger)m2); + result = (T)result2; } else if (m1 instanceof Long || m2 instanceof Long) { Long result2 = (m1.longValue() + m2.longValue()); - result = (T) result2; + result = (T)result2; } else if (m1 instanceof Double || m2 instanceof Double) { Double result2 = (m1.doubleValue() + m2.doubleValue()); - result = (T) result2; + result = (T)result2; } else if (m1 instanceof Float || m2 instanceof Float) { Float result2 = (m1.floatValue() + m2.floatValue()); - result = (T) result2; + result = (T)result2; } else { // Integer Integer result2 = (m1.intValue() + m2.intValue()); - result = (T) result2; + result = (T)result2; } output.set(r, c, result); } @@ -207,24 +207,24 @@ public Matrix subtract(Matrix input) { T result; /* TODO: This is ugly and how to handle number overflow? */ if (m1 instanceof BigDecimal || m2 instanceof BigDecimal) { - BigDecimal result2 = ((BigDecimal) m1).subtract((BigDecimal) m2); - result = (T) result2; + BigDecimal result2 = ((BigDecimal)m1).subtract((BigDecimal)m2); + result = (T)result2; } else if (m1 instanceof BigInteger || m2 instanceof BigInteger) { - BigInteger result2 = ((BigInteger) m1).subtract((BigInteger) m2); - result = (T) result2; + BigInteger result2 = ((BigInteger)m1).subtract((BigInteger)m2); + result = (T)result2; } else if (m1 instanceof Long || m2 instanceof Long) { Long result2 = (m1.longValue() - m2.longValue()); - result = (T) result2; + result = (T)result2; } else if (m1 instanceof Double || m2 instanceof Double) { Double result2 = (m1.doubleValue() - m2.doubleValue()); - result = (T) result2; + result = (T)result2; } else if (m1 instanceof Float || m2 instanceof Float) { Float result2 = (m1.floatValue() - m2.floatValue()); - result = (T) result2; + result = (T)result2; } else { // Integer Integer result2 = (m1.intValue() - m2.intValue()); - result = (T) result2; + result = (T)result2; } output.set(r, c, result); } @@ -250,20 +250,20 @@ public Matrix multiply(Matrix input) { T m1 = row[i]; T m2 = column[i]; - BigDecimal result2 = ((BigDecimal) m1).multiply(((BigDecimal) m2)); + BigDecimal result2 = ((BigDecimal)m1).multiply(((BigDecimal)m2)); result = result.add(result2); } - output.set(r, c, (T) result); + output.set(r, c, (T)result); } else if (test instanceof BigInteger) { BigInteger result = BigInteger.ZERO; for (int i = 0; i < cols; i++) { T m1 = row[i]; T m2 = column[i]; - BigInteger result2 = ((BigInteger) m1).multiply(((BigInteger) m2)); + BigInteger result2 = ((BigInteger)m1).multiply(((BigInteger)m2)); result = result.add(result2); } - output.set(r, c, (T) result); + output.set(r, c, (T)result); } else if (test instanceof Long) { Long result = 0l; for (int i = 0; i < cols; i++) { @@ -271,9 +271,9 @@ public Matrix multiply(Matrix input) { T m2 = column[i]; Long result2 = m1.longValue() * m2.longValue(); - result = result + result2; + result = result+result2; } - output.set(r, c, (T) result); + output.set(r, c, (T)result); } else if (test instanceof Double) { Double result = 0d; for (int i = 0; i < cols; i++) { @@ -281,9 +281,9 @@ public Matrix multiply(Matrix input) { T m2 = column[i]; Double result2 = m1.doubleValue() * m2.doubleValue(); - result = result + result2; + result = result+result2; } - output.set(r, c, (T) result); + output.set(r, c, (T)result); } else if (test instanceof Float) { Float result = 0f; for (int i = 0; i < cols; i++) { @@ -291,9 +291,9 @@ public Matrix multiply(Matrix input) { T m2 = column[i]; Float result2 = m1.floatValue() * m2.floatValue(); - result = result + result2; + result = result+result2; } - output.set(r, c, (T) result); + output.set(r, c, (T)result); } else { // Integer Integer result = 0; @@ -302,9 +302,9 @@ public Matrix multiply(Matrix input) { T m2 = column[i]; Integer result2 = m1.intValue() * m2.intValue(); - result = result + result2; + result = result+result2; } - output.set(r, c, (T) result); + output.set(r, c, (T)result); } } } @@ -345,11 +345,11 @@ public boolean equals(Object obj) { return false; if (this.cols != m.cols) return false; - for (int i = 0; i < matrix.length; i++) { + for (int i=0; i getU() { } public List getPermutation() { - return new ArrayList<>(Arrays.asList(permutation)); + return new ArrayList(Arrays.asList(permutation)); } public LUDecomposition(Matrix input) { From 2e470b0a6c66cf3bdd9d8def4b4e31e07ac04754 Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Tue, 4 Jul 2017 16:00:34 -0400 Subject: [PATCH 37/88] Code clean-up --- .../mathematics/LUDecomposition.java | 21 ++++++++++++------- .../mathematics/test/LUDecompositionTest.java | 2 +- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/com/jwetherell/algorithms/mathematics/LUDecomposition.java b/src/com/jwetherell/algorithms/mathematics/LUDecomposition.java index 6eebd617..3ff2ec3b 100644 --- a/src/com/jwetherell/algorithms/mathematics/LUDecomposition.java +++ b/src/com/jwetherell/algorithms/mathematics/LUDecomposition.java @@ -10,15 +10,17 @@ * LU decomposition of matrix M produces 2 matrices L and U such that M = L*U * where L is lower triangular matrix and U is upper triangular matrix *

- * https://en.wikipedia.org/wiki/LU_decomposition + * @see LU Decomposition (Wikipedia) *
* @author Mateusz Cianciara + * @author Justin Wetherell */ public class LUDecomposition { + + private int n = 0; private Double[][] L = null; private Double[][] A = null; private Integer[] permutation = null; - private int n = 0; public Matrix getL() { return new Matrix(n, n, L); @@ -33,9 +35,9 @@ public List getPermutation() { } public LUDecomposition(Matrix input) { - if (input.getCols() != input.getRows()) { + if (input.getCols() != input.getRows()) throw new IllegalArgumentException("Matrix is not square"); - } + n = input.getCols(); L = new Double[n][n]; A = new Double[n][n]; @@ -68,22 +70,25 @@ public LUDecomposition(Matrix input) { double temp = A[row][i]; A[row][i] = A[max_in_col][i]; A[max_in_col][i] = temp; + if (i < row) { temp = L[row][i]; L[row][i] = L[max_in_col][i]; L[max_in_col][i] = temp; } } - int temp = permutation[row]; + final int temp = permutation[row]; permutation[row] = permutation[max_in_col]; permutation[max_in_col] = temp; } + //zero column number row - double p = A[row][row]; - if (p == 0) return; + final double p = A[row][row]; + if (p == 0) + return; for (int i = row + 1; i < n; i++) { - double y = A[i][row]; + final double y = A[i][row]; L[i][row] = y / p; for (int j = row; j < n; j++) { diff --git a/test/com/jwetherell/algorithms/mathematics/test/LUDecompositionTest.java b/test/com/jwetherell/algorithms/mathematics/test/LUDecompositionTest.java index cd5d0246..d52f4e65 100644 --- a/test/com/jwetherell/algorithms/mathematics/test/LUDecompositionTest.java +++ b/test/com/jwetherell/algorithms/mathematics/test/LUDecompositionTest.java @@ -6,8 +6,8 @@ import static org.junit.Assert.*; - public class LUDecompositionTest { + private boolean epsiMatrixCompare(Matrix a, Matrix b, double epsi) { if (a.getRows() != b.getRows() || a.getCols() != b.getCols()) { throw new IllegalArgumentException("Matrices are not the same shape"); From 025fca6b83e3a672ac3f2f32cd70ac617ecb426a Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Wed, 9 Aug 2017 15:18:54 -0400 Subject: [PATCH 38/88] Fix a root==null bug in the toString --- .../jwetherell/algorithms/data_structures/PatriciaTrie.java | 2 ++ src/com/jwetherell/algorithms/data_structures/Treap.java | 3 ++- src/com/jwetherell/algorithms/data_structures/Trie.java | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/com/jwetherell/algorithms/data_structures/PatriciaTrie.java b/src/com/jwetherell/algorithms/data_structures/PatriciaTrie.java index b3bce4bc..89644b07 100644 --- a/src/com/jwetherell/algorithms/data_structures/PatriciaTrie.java +++ b/src/com/jwetherell/algorithms/data_structures/PatriciaTrie.java @@ -524,6 +524,8 @@ protected static interface INodeCreator { protected static class PatriciaTriePrinter { protected static String getString(PatriciaTrie tree) { + if (tree.root == null) + return "Tree has no nodes."; return getString(tree.root, "", null, true); } diff --git a/src/com/jwetherell/algorithms/data_structures/Treap.java b/src/com/jwetherell/algorithms/data_structures/Treap.java index 79792f37..01ea0c45 100644 --- a/src/com/jwetherell/algorithms/data_structures/Treap.java +++ b/src/com/jwetherell/algorithms/data_structures/Treap.java @@ -182,7 +182,8 @@ public String toString() { protected static class TreapPrinter { public static > String getString(Treap tree) { - if (tree.root == null) return "Tree has no nodes."; + if (tree.root == null) + return "Tree has no nodes."; return getString((TreapNode) tree.root, "", true); } diff --git a/src/com/jwetherell/algorithms/data_structures/Trie.java b/src/com/jwetherell/algorithms/data_structures/Trie.java index 7ff1bfd2..051035ea 100644 --- a/src/com/jwetherell/algorithms/data_structures/Trie.java +++ b/src/com/jwetherell/algorithms/data_structures/Trie.java @@ -350,6 +350,8 @@ public static void print(Trie trie) { } public static String getString(Trie tree) { + if (tree.root == null) + return "Tree has no nodes."; return getString(tree.root, "", null, true); } From 5a34ea8598204ea6babae497037b2a9a5897535a Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Wed, 9 Aug 2017 15:19:38 -0400 Subject: [PATCH 39/88] Added a method to provide your own data to the test Utils class --- .../data_structures/test/common/Utils.java | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/test/com/jwetherell/algorithms/data_structures/test/common/Utils.java b/test/com/jwetherell/algorithms/data_structures/test/common/Utils.java index 1dfaa146..83ec3fd4 100644 --- a/test/com/jwetherell/algorithms/data_structures/test/common/Utils.java +++ b/test/com/jwetherell/algorithms/data_structures/test/common/Utils.java @@ -42,6 +42,30 @@ public static void handleError(Object[] data, Object obj) { private static final Random RANDOM = new Random(); + public static TestData testData(int... integers) { + TestData data = new TestData(integers.length); + + StringBuilder builder = new StringBuilder(); + data.unsorted = new Integer[integers.length]; + java.util.Set set = new java.util.HashSet(); + builder.append("Array="); + for (int i = 0; i < integers.length; i++) { + Integer j = integers[i]; + data.unsorted[i] = j; + if (i != integers.length-1) + builder.append(j).append(','); + } + set.clear(); + set = null; + builder.append('\n'); + data.string = builder.toString(); + + data.sorted = Arrays.copyOf(data.unsorted, data.unsorted.length); + Arrays.sort(data.sorted); + + return data; + } + public static TestData generateTestData(int data_size) { TestData data = new TestData(data_size); @@ -63,7 +87,8 @@ public static TestData generateTestData(int data_size) { } } data.unsorted[i] = j; - if (i!=data_size-1) builder.append(j).append(','); + if (i != data_size-1) + builder.append(j).append(','); } set.clear(); set = null; From b27e2b158c5bf1ad5515d74d134986d69a053fb8 Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Wed, 9 Aug 2017 15:19:59 -0400 Subject: [PATCH 40/88] Added ternary search tree --- .../data_structures/TernarySearchTree.java | 409 ++++++++++++++++++ .../test/TernarySearchTreeTests.java | 75 ++++ 2 files changed, 484 insertions(+) create mode 100644 src/com/jwetherell/algorithms/data_structures/TernarySearchTree.java create mode 100644 test/com/jwetherell/algorithms/data_structures/test/TernarySearchTreeTests.java diff --git a/src/com/jwetherell/algorithms/data_structures/TernarySearchTree.java b/src/com/jwetherell/algorithms/data_structures/TernarySearchTree.java new file mode 100644 index 00000000..4b9d8dc4 --- /dev/null +++ b/src/com/jwetherell/algorithms/data_structures/TernarySearchTree.java @@ -0,0 +1,409 @@ +package com.jwetherell.algorithms.data_structures; + +import com.jwetherell.algorithms.data_structures.interfaces.ITree; + +/** + * In computer science, a ternary search tree is a type of trie (sometimes called a prefix tree) where nodes are arranged in a manner similar to a binary search tree, but with up to three + * children rather than the binary tree's limit of two. + *
+ * This implementation is based on Jon Bentley and Bob Sedgewick's paper. + *

+ * @see Ternary Search Tree (Wikipedia) + *
+ * @author Justin Wetherell + */ +public class TernarySearchTree implements ITree { + + protected INodeCreator creator; + protected Node root; + + private int size = 0; + + public TernarySearchTree() { + this.creator = new INodeCreator() { + /** + * {@inheritDoc} + */ + @Override + public Node createNewNode(Node parent, Character character, boolean isWord) { + return (new Node(parent, character, isWord)); + } + }; + } + + /** + * Constructor with external Node creator. + */ + public TernarySearchTree(INodeCreator creator) { + this.creator = creator; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean add(C value) { + if (value == null) + return false; + + final int before = size; + if (root == null) { + this.root = insert(null, null, value, 0);; + } else { + insert(null, root, value, 0); + } + final int after = size; + return (before= value.length()) + return null; + + final char c = value.charAt(idx); + final boolean isWord = (idx==(value.length()-1)); + + if (node == null) { + // Create new node + node = this.creator.createNewNode(parent, c, isWord); + + // If new node represents a "word", increase the size + if (isWord) + size++; + } else if (c==node.character && isWord && !node.isWord) { + // Changing an existing node into a "word" node + node.isWord = true; + // Increase the size + size++; + } + + if (c < node.character) { + node.loKid = insert(node, node.loKid, value, idx); + } else if (c > node.character) { + node.hiKid = insert(node, node.hiKid, value, idx); + } else if (idx < (value.length()-1)) { + // Not done with whole string yet + node.kid = insert(node, node.kid, value, ++idx); + } + return node; + } + + /** + * {@inheritDoc} + */ + @Override + public C remove(C value) { + if (value == null || root == null) + return null; + + // Find the node + final Node node = search(root, value, 0); + + // If node was found, remove from tree + if (node != null) { + if (node.isWord) { + node.isWord = false; + remove(node); + size--; + return value; + } + } + return null; + } + + private void remove(Node node) { + final Node parent = node.parent; + // If node does not represent a word and has no children + if (!node.isWord && node.loKid==null && node.kid==null && node.hiKid==null) { + // Remove node from parent + if (parent!=null && parent.loKid==node) { + parent.loKid = null; + } else if (parent!=null && parent.hiKid==node) { + parent.hiKid = null; + } else if (parent!=null && parent.kid==node) { + parent.kid = null; + } + + if (parent != null) { + // Go up the tree and prune + remove(parent); + } else { + // If node doesn't have a parent, it's root. + this.root = null; + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public void clear() { + root = null; + size = 0; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean contains(C value) { + if (value == null) + return false; + + // Find the node + final Node node = search(root, value, 0); + // If node isn't null and it represents a "word" then the tree contains the value + return (node!=null && node.isWord); + } + + private Node search(Node node, C value, int idx) { + if (node == null || idx>=value.length()) + return null; + + final char c = value.charAt(idx); + + if (c < node.character) + return search(node.loKid, value, idx); + if (c > node.character) + return search(node.hiKid, value, idx); + if (++idx < value.length()) + return search(node.kid, value, idx); + return node; + } + + @Override + public int size() { + return size; + } + + @Override + public boolean validate() { + if (this.root == null) + return true; + + return validate(root); + } + + private boolean validate(Node node) { + if (node.loKid != null) { + if (node.loKid.character >= node.character) + return false; + return validate(node.loKid); + } + if (node.kid != null) { + return validate(node.kid); + } + if (node.hiKid != null) { + if (node.hiKid.character <= node.character) + return false; + return validate(node.hiKid); + } + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public java.util.Collection toCollection() { + return (new JavaCompatibleTree(this)); + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + return TreePrinter.getString(this); + } + + protected static interface INodeCreator { + + /** + * Create a new node for sequence. + * + * @param parent + * node of the new node. + * @param character + * which represents this node. + * @param isWord + * signifies if the node represents a word. + * @return Node which was created. + */ + public Node createNewNode(Node parent, Character character, boolean isWord); + } + + protected static class TreePrinter { + + public static void print(TernarySearchTree tree) { + System.out.println(getString(tree)); + } + + public static String getString(TernarySearchTree tree) { + if (tree.root == null) + return "Tree has no nodes."; + return getString(tree.root, "", null, true); + } + + protected static String getString(Node node, String prefix, String previousString, boolean isTail) { + final StringBuilder builder = new StringBuilder(); + final String string; + final String temp = String.valueOf(node.character); + if (previousString != null) + string = previousString + temp; + else + string = temp; + builder.append(prefix + (isTail ? "└── " : "├── ") + ((node.isWord == true) ? + ("(" + node.character + ") " + string) + : + node.character) + "\n" + ); + if (node.loKid != null) + builder.append(getString(node.loKid, prefix + (isTail ? " " : "│ "), string.substring(0, string.length()-1), false)); + if (node.kid != null) + builder.append(getString(node.kid, prefix + (isTail ? " " : "│ "), string, false)); + if (node.hiKid != null) + builder.append(getString(node.hiKid, prefix + (isTail ? " " : "│ "), string.substring(0, string.length()-1), true)); + return builder.toString(); + } + } + + protected static class Node { + + private final Node parent; + private final char character; + + private boolean isWord; + + protected Node loKid; + protected Node kid; + protected Node hiKid; + + protected Node(Node parent, char character, boolean isWord) { + this.parent = parent; + this.character = character; + this.isWord = isWord; + } + } + + @SuppressWarnings("unchecked") + public static class JavaCompatibleTree extends java.util.AbstractCollection { + + private TernarySearchTree tree = null; + + public JavaCompatibleTree(TernarySearchTree tree) { + this.tree = tree; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean add(C value) { + return tree.add(value); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean remove(Object value) { + return (tree.remove((C)value)!=null); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean contains(Object value) { + return tree.contains((C)value); + } + + /** + * {@inheritDoc} + */ + @Override + public int size() { + return tree.size; + } + + /** + * {@inheritDoc} + * + * WARNING: This iterator makes a copy of the tree's contents during it's construction! + */ + @Override + public java.util.Iterator iterator() { + return (new TreeIterator(tree)); + } + + private static class TreeIterator implements java.util.Iterator { + + private TernarySearchTree tree = null; + private TernarySearchTree.Node lastNode = null; + private java.util.Iterator> iterator = null; + + protected TreeIterator(TernarySearchTree tree) { + this.tree = tree; + java.util.Map map = new java.util.LinkedHashMap(); + if (this.tree.root!=null) { + getNodesWhichRepresentsWords(this.tree.root,"",map); + } + iterator = map.entrySet().iterator(); + } + + private void getNodesWhichRepresentsWords(TernarySearchTree.Node node, String string, java.util.Map nodesMap) { + StringBuilder builder = new StringBuilder(string); + builder.append(node.character); + if (node.isWord) + nodesMap.put(node,builder.toString()); + if (node.loKid != null) { + Node child = node.loKid; + getNodesWhichRepresentsWords(child, builder.subSequence(0, builder.length()-1).toString(), nodesMap); + } + if (node.kid != null) { + Node child = node.kid; + getNodesWhichRepresentsWords(child, builder.toString(), nodesMap); + } + if (node.hiKid != null) { + Node child = node.hiKid; + getNodesWhichRepresentsWords(child, builder.subSequence(0, builder.length()-1).toString(), nodesMap); + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean hasNext() { + if (iterator!=null && iterator.hasNext()) + return true; + return false; + } + + /** + * {@inheritDoc} + */ + @Override + public C next() { + if (iterator==null) return null; + + java.util.Map.Entry entry = iterator.next(); + lastNode = entry.getKey(); + return (C)entry.getValue(); + } + + /** + * {@inheritDoc} + */ + @Override + public void remove() { + if (iterator==null || tree==null) return; + + iterator.remove(); + this.tree.remove(lastNode); + } + } + } +} diff --git a/test/com/jwetherell/algorithms/data_structures/test/TernarySearchTreeTests.java b/test/com/jwetherell/algorithms/data_structures/test/TernarySearchTreeTests.java new file mode 100644 index 00000000..24d46297 --- /dev/null +++ b/test/com/jwetherell/algorithms/data_structures/test/TernarySearchTreeTests.java @@ -0,0 +1,75 @@ +package com.jwetherell.algorithms.data_structures.test; + +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import junit.framework.Assert; + +import org.junit.Test; + +import com.jwetherell.algorithms.data_structures.TernarySearchTree; +import com.jwetherell.algorithms.data_structures.test.common.JavaCollectionTest; +import com.jwetherell.algorithms.data_structures.test.common.TreeTest; +import com.jwetherell.algorithms.data_structures.test.common.Utils; +import com.jwetherell.algorithms.data_structures.test.common.Utils.TestData; + +public class TernarySearchTreeTests { + + @Test + public void test1() { + final List tests = new ArrayList(); + tests.add("BEE"); + tests.add("BEEN"); + tests.add("BEAST"); + tests.add("BELOW"); + tests.add("BEFORE"); + tests.add("BUT"); + tests.add("CAT"); + tests.add("BE"); + tests.add("B"); + + final TernarySearchTree bst = new TernarySearchTree(); + + // Add + bst.add(null); + bst.add(""); + for (String s : tests) + bst.add(s); + bst.add(null); + bst.add(""); + Assert.assertFalse(bst.add("BE")); + + // contains + Assert.assertFalse(bst.contains(null)); + Assert.assertFalse(bst.contains("")); + for (String s : tests) + Assert.assertTrue(bst.contains(s)); + Assert.assertFalse(bst.contains(null)); + Assert.assertFalse(bst.contains("")); + + // remove + Assert.assertTrue(bst.remove(null)==null); + Assert.assertTrue(bst.remove("")==null); + for (String s : tests) + Assert.assertTrue(bst.remove(s)!=null); + Assert.assertTrue(bst.remove(null)==null); + Assert.assertTrue(bst.remove("")==null); + } + + @Test + public void testTernary() { + TestData data = Utils.generateTestData(1000); + + String bstName = "TernarySearchTreeTests"; + TernarySearchTree bst = new TernarySearchTree(); + Collection bstCollection = bst.toCollection(); + + assertTrue(TreeTest.testTree(bst, String.class, bstName, + data.unsorted, data.invalid)); + assertTrue(JavaCollectionTest.testCollection(bstCollection, String.class, bstName, + data.unsorted, data.sorted, data.invalid)); + } +} From b5134b81fca8cf3b6fac25357edb66731b44edb8 Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Wed, 9 Aug 2017 15:36:02 -0400 Subject: [PATCH 41/88] Simplified code in TernarySearchTree --- .../data_structures/TernarySearchTree.java | 43 +++++++++++++------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/src/com/jwetherell/algorithms/data_structures/TernarySearchTree.java b/src/com/jwetherell/algorithms/data_structures/TernarySearchTree.java index 4b9d8dc4..f89f3b56 100644 --- a/src/com/jwetherell/algorithms/data_structures/TernarySearchTree.java +++ b/src/com/jwetherell/algorithms/data_structures/TernarySearchTree.java @@ -113,18 +113,18 @@ public C remove(C value) { private void remove(Node node) { final Node parent = node.parent; + // If node does not represent a word and has no children if (!node.isWord && node.loKid==null && node.kid==null && node.hiKid==null) { - // Remove node from parent - if (parent!=null && parent.loKid==node) { - parent.loKid = null; - } else if (parent!=null && parent.hiKid==node) { - parent.hiKid = null; - } else if (parent!=null && parent.kid==node) { - parent.kid = null; - } - if (parent != null) { + // Remove node from parent + if (parent.loKid==node) { + parent.loKid = null; + } else if (parent.hiKid==node) { + parent.hiKid = null; + } else if (parent.kid==node) { + parent.kid = null; + } // Go up the tree and prune remove(parent); } else { @@ -153,6 +153,7 @@ public boolean contains(C value) { // Find the node final Node node = search(root, value, 0); + // If node isn't null and it represents a "word" then the tree contains the value return (node!=null && node.isWord); } @@ -285,6 +286,22 @@ protected Node(Node parent, char character, boolean isWord) { this.character = character; this.isWord = isWord; } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("char=").append(this.character).append('\n'); + if (this.loKid != null) + builder.append('\t').append("lo=").append(this.loKid.character).append('\n'); + if (this.kid != null) + builder.append('\t').append("eq=").append(this.kid.character).append('\n'); + if (this.hiKid != null) + builder.append('\t').append("hi=").append(this.hiKid.character).append('\n'); + return builder.toString(); + } } @SuppressWarnings("unchecked") @@ -354,7 +371,7 @@ protected TreeIterator(TernarySearchTree tree) { } private void getNodesWhichRepresentsWords(TernarySearchTree.Node node, String string, java.util.Map nodesMap) { - StringBuilder builder = new StringBuilder(string); + final StringBuilder builder = new StringBuilder(string); builder.append(node.character); if (node.isWord) nodesMap.put(node,builder.toString()); @@ -387,7 +404,8 @@ public boolean hasNext() { */ @Override public C next() { - if (iterator==null) return null; + if (iterator==null) + return null; java.util.Map.Entry entry = iterator.next(); lastNode = entry.getKey(); @@ -399,7 +417,8 @@ public C next() { */ @Override public void remove() { - if (iterator==null || tree==null) return; + if (iterator==null || tree==null) + return; iterator.remove(); this.tree.remove(lastNode); From 96ad312fc1ef2feb3b61ad6b65baf81609f5236d Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Wed, 9 Aug 2017 15:37:17 -0400 Subject: [PATCH 42/88] Added Ternary Search Tree to README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 930ae6a0..060ebde8 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,7 @@ This is a collection of algorithms and data structures which I've implement over * [Suffix Array](src/com/jwetherell/algorithms/data_structures/SuffixArray.java) * [Suffix Tree (Ukkonen's algorithm)](src/com/jwetherell/algorithms/data_structures/SuffixTree.java) * [Suffix Trie [backed by a Trie]](src/com/jwetherell/algorithms/data_structures/SuffixTrie.java) +* [Ternary Search Tree](src/com/jwetherell/algorithms/data_structures/TernarySearchTree.java) * [Treap](src/com/jwetherell/algorithms/data_structures/Treap.java) * [Tree Map (associative array) [backed by an AVL Tree]](src/com/jwetherell/algorithms/data_structures/TreeMap.java) * [Trie](src/com/jwetherell/algorithms/data_structures/Trie.java) From 833341a4c552617d7ebafad318bc10e562d8784d Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Thu, 10 Aug 2017 10:41:59 -0400 Subject: [PATCH 43/88] Code simplification in Ternary Search Tree --- .../data_structures/TernarySearchTree.java | 114 ++++++++++-------- .../test/TernarySearchTreeTests.java | 2 + 2 files changed, 66 insertions(+), 50 deletions(-) diff --git a/src/com/jwetherell/algorithms/data_structures/TernarySearchTree.java b/src/com/jwetherell/algorithms/data_structures/TernarySearchTree.java index f89f3b56..3c034afc 100644 --- a/src/com/jwetherell/algorithms/data_structures/TernarySearchTree.java +++ b/src/com/jwetherell/algorithms/data_structures/TernarySearchTree.java @@ -47,13 +47,14 @@ public boolean add(C value) { return false; final int before = size; - if (root == null) { - this.root = insert(null, null, value, 0);; - } else { + if (root == null) + this.root = insert(null, null, value, 0); + else insert(null, root, value, 0); - } final int after = size; - return (before node.character) return search(node.hiKid, value, idx); - if (++idx < value.length()) - return search(node.kid, value, idx); + if (idx < (value.length()-1)) { + // c == node.char and there is still some characters left in the search string + return search(node.kid, value, ++idx); + } return node; } @@ -182,24 +191,33 @@ public int size() { public boolean validate() { if (this.root == null) return true; - return validate(root); } private boolean validate(Node node) { + boolean result = false; if (node.loKid != null) { if (node.loKid.character >= node.character) return false; - return validate(node.loKid); + result = validate(node.loKid); + if (!result) + return false; } + if (node.kid != null) { - return validate(node.kid); + result = validate(node.kid); + if (!result) + return false; } + if (node.hiKid != null) { if (node.hiKid.character <= node.character) return false; - return validate(node.hiKid); + result = validate(node.hiKid); + if (!result) + return false; } + return true; } @@ -249,23 +267,20 @@ public static String getString(TernarySearchTree tre protected static String getString(Node node, String prefix, String previousString, boolean isTail) { final StringBuilder builder = new StringBuilder(); - final String string; - final String temp = String.valueOf(node.character); + String string = ""; if (previousString != null) - string = previousString + temp; - else - string = temp; + string = previousString; builder.append(prefix + (isTail ? "└── " : "├── ") + ((node.isWord == true) ? - ("(" + node.character + ") " + string) + ("(" + node.character + ") " + string+String.valueOf(node.character)) : node.character) + "\n" ); if (node.loKid != null) - builder.append(getString(node.loKid, prefix + (isTail ? " " : "│ "), string.substring(0, string.length()-1), false)); + builder.append(getString(node.loKid, prefix + (isTail ? " " : "│ "), string, false)); if (node.kid != null) - builder.append(getString(node.kid, prefix + (isTail ? " " : "│ "), string, false)); + builder.append(getString(node.kid, prefix + (isTail ? " " : "│ "), string+String.valueOf(node.character), false)); if (node.hiKid != null) - builder.append(getString(node.hiKid, prefix + (isTail ? " " : "│ "), string.substring(0, string.length()-1), true)); + builder.append(getString(node.hiKid, prefix + (isTail ? " " : "│ "), string, true)); return builder.toString(); } } @@ -372,20 +387,19 @@ protected TreeIterator(TernarySearchTree tree) { private void getNodesWhichRepresentsWords(TernarySearchTree.Node node, String string, java.util.Map nodesMap) { final StringBuilder builder = new StringBuilder(string); - builder.append(node.character); if (node.isWord) nodesMap.put(node,builder.toString()); if (node.loKid != null) { Node child = node.loKid; - getNodesWhichRepresentsWords(child, builder.subSequence(0, builder.length()-1).toString(), nodesMap); + getNodesWhichRepresentsWords(child, builder.toString(), nodesMap); } if (node.kid != null) { Node child = node.kid; - getNodesWhichRepresentsWords(child, builder.toString(), nodesMap); + getNodesWhichRepresentsWords(child, builder.append(node.character).toString(), nodesMap); } if (node.hiKid != null) { Node child = node.hiKid; - getNodesWhichRepresentsWords(child, builder.subSequence(0, builder.length()-1).toString(), nodesMap); + getNodesWhichRepresentsWords(child, builder.toString(), nodesMap); } } diff --git a/test/com/jwetherell/algorithms/data_structures/test/TernarySearchTreeTests.java b/test/com/jwetherell/algorithms/data_structures/test/TernarySearchTreeTests.java index 24d46297..82a5b70a 100644 --- a/test/com/jwetherell/algorithms/data_structures/test/TernarySearchTreeTests.java +++ b/test/com/jwetherell/algorithms/data_structures/test/TernarySearchTreeTests.java @@ -30,6 +30,8 @@ public void test1() { tests.add("CAT"); tests.add("BE"); tests.add("B"); + tests.add("DAD"); + tests.add("APPLE"); final TernarySearchTree bst = new TernarySearchTree(); From c277f19b4ae061abaaa0bd23b397f225abf3bbe7 Mon Sep 17 00:00:00 2001 From: Szymon Stankiewicz Date: Mon, 4 Sep 2017 23:18:05 +0200 Subject: [PATCH 44/88] Fixed travis.yml due to Oracle's withdrawal --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7d90cbb7..09427de6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ before_script: + - sudo apt-get install ant-optional - export OPTS="-server -Xmx3072M" - export JAVA_OPTS="${JAVA_OPTS} ${OPTS}" - export ANT_OPTS="${ANT_OPTS} ${OPTS}" @@ -9,12 +10,12 @@ language: java jdk: - oraclejdk8 - - oraclejdk7 +# - oraclejdk7 # - oraclejdk6 # - openjdk8 - openjdk7 - - openjdk6 +# - openjdk6 env: - TEST_SUITE=run_tests From da73ae811cf90b0381997100fdaf9f558d17f9d2 Mon Sep 17 00:00:00 2001 From: Szymon Stankiewicz Date: Mon, 4 Sep 2017 23:18:26 +0200 Subject: [PATCH 45/88] Implementation of interval sum data structure. --- .../data_structures/IntervalSumArray.java | 160 ++++++++++++++++++ .../data_structures/IntervalSumArrayTest.java | 89 ++++++++++ 2 files changed, 249 insertions(+) create mode 100644 src/com/jwetherell/algorithms/data_structures/IntervalSumArray.java create mode 100644 test/com/jwetherell/algorithms/data_structures/IntervalSumArrayTest.java diff --git a/src/com/jwetherell/algorithms/data_structures/IntervalSumArray.java b/src/com/jwetherell/algorithms/data_structures/IntervalSumArray.java new file mode 100644 index 00000000..4f567ef5 --- /dev/null +++ b/src/com/jwetherell/algorithms/data_structures/IntervalSumArray.java @@ -0,0 +1,160 @@ +package com.jwetherell.algorithms.data_structures; + + +/** + * Implementation of array holding integer values which allows to count sum of elements in given + * interval in O(log n) complexity. + * + * @author Szymon Stankiewicz + */ +public class IntervalSumArray { + private List.ArrayList values = new List.ArrayList<>(); + private List.ArrayList prefSums = new List.ArrayList<>(); + + /** + * Creates empty IntervalSumArray + */ + public IntervalSumArray() { + values.add(0); + prefSums.add(0); + } + + /** + * Creates IntervalSumArray of given size filled with zeros. + * + * Complexity O(size). + * + * @param size size of IntervalSumArray + */ + public IntervalSumArray(int size) { + this(); + for(int i = 0; i values) { + this(); + for(Integer v: values) + add(v); + } + + private static int greatestPowerOfTwoDividing(int x) { + return x&(-x); + } + + private static int successor(int x) { + return x + greatestPowerOfTwoDividing(x); + } + + private static int predecessor(int x) { + return x - greatestPowerOfTwoDividing(x); + } + + /** + * @return size of IntervalSumArray + */ + public int size() { + return prefSums.size() - 1; + } + + /** + * Adds value at the end of IntervalSumArray. + * + * Complexity O(log n). + * + * @param val value to be added at the end of array. + */ + public void add(int val) { + values.add(val); + for(int i = 1; i= size()) throw new IndexOutOfBoundsException(); + index++; + int diff = val - values.get(index); + values.set(index, val); + while(index <= size()) { + int oldPrefSum = prefSums.get(index); + prefSums.set(index, oldPrefSum + diff); + index = successor(index); + } + } + + /** + * Return value with given index. + * + * Complexity O(1) + * + * @param index index of array. + * @return value at given index. + */ + public int get(int index) { + return values.get(index+1); + } + + /** + * Return sum of values from 0 to end inclusively. + * + * Complexity O(log n) + * + * @param end end of interval + * @return sum of values in interval + */ + public int sum(int end) { + if(end < 0 || end >= size()) throw new IndexOutOfBoundsException(); + end++; + int s = 0; + while(end > 0) { + s += prefSums.get(end); + end = predecessor(end); + } + return s; + } + + /** + * Return sum of all values inclusively. + * + * Complexity O(log n) + * + * @return sum of values in array + */ + public int sum() { + return sum(size()-1); + } + + /** + * Return sum of values from start to end inclusively. + * + * Complexity O(log n) + * + * @param start start of interval + * @param end end of interval + * @return sum of values in interval + */ + public int sum(int start, int end) { + if(start > end) throw new IllegalArgumentException("Start must be less then end"); + int startPrefSum = start == 0 ? 0 : sum(start-1); + int endPrefSum = sum(end); + return endPrefSum - startPrefSum; + } +} diff --git a/test/com/jwetherell/algorithms/data_structures/IntervalSumArrayTest.java b/test/com/jwetherell/algorithms/data_structures/IntervalSumArrayTest.java new file mode 100644 index 00000000..0af23a19 --- /dev/null +++ b/test/com/jwetherell/algorithms/data_structures/IntervalSumArrayTest.java @@ -0,0 +1,89 @@ +package com.jwetherell.algorithms.data_structures; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import static org.junit.Assert.*; + +public class IntervalSumArrayTest { + + @Test + public void properSumAllElementsTest() { + IntervalSumArray sub = new IntervalSumArray(); + for(int i = 0; i<=100; i++) + sub.add(i); + for(int i = 0; i<=100; i++) + assertEquals(i*(i+1)/2, sub.sum(i)); + assertEquals(100*101/2, sub.sum()); + } + + @Test + public void randomGeneratedTest() { + Random generator = new Random(42); + List list = new ArrayList<>(); + for(int i = 0; i<=100; i++) + list.add(i); + IntervalSumArray sum = new IntervalSumArray(list); + for(int i = 0; i<1000000; i++) { + int pos = generator.nextInt(100); + int val = generator.nextInt(2000000) - 1000000; + sum.set(pos, val); + list.set(pos, val); + assertEquals(val, sum.get(pos)); + } + + int s = 0; + List prefSum = new ArrayList<>(); + prefSum.add(s); + for(Integer val: list) { + s += val; + prefSum.add(s); + } + + for(int i = 0; i<=100; i++) { + for(int j = i; j<=100; j++) { + assertEquals(prefSum.get(j+1) - prefSum.get(i), sum.sum(i, j)); + } + } + } + + @Test + public void setIndexOutOfRangeTest() { + IntervalSumArray sum = new IntervalSumArray(100); + boolean thrown = false; + try { + sum.set(101, 10); + } catch (IndexOutOfBoundsException e) { + thrown = true; + } + assertTrue(thrown); + } + + @Test + public void sumIndexOutOfRangeTest() { + IntervalSumArray sum = new IntervalSumArray(100); + boolean thrown = false; + try { + sum.sum(101); + } catch (IndexOutOfBoundsException e) { + thrown = true; + } + assertTrue(thrown); + } + + @Test + public void endBeforeStartTest() { + IntervalSumArray sum = new IntervalSumArray(100); + boolean thrown = false; + try { + sum.sum(101, 100); + } catch (IllegalArgumentException e) { + thrown = true; + } + assertTrue(thrown); + } + +} \ No newline at end of file From 6163af36548bd46b6a62cd87558d23abd11870a3 Mon Sep 17 00:00:00 2001 From: Szymon Stankiewicz Date: Tue, 5 Sep 2017 02:22:23 +0200 Subject: [PATCH 46/88] Implementation of lowest common ancestor. --- .travis.yml | 6 +- README.md | 3 + .../algorithms/data_structures/Tree.java | 135 ++++++++++++++++++ .../algorithms/data_structures/TreeTest.java | 43 ++++++ 4 files changed, 184 insertions(+), 3 deletions(-) create mode 100644 src/com/jwetherell/algorithms/data_structures/Tree.java create mode 100644 test/com/jwetherell/algorithms/data_structures/TreeTest.java diff --git a/.travis.yml b/.travis.yml index 7d90cbb7..58364da4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ before_script: + - sudo apt-get install ant-optional - export OPTS="-server -Xmx3072M" - export JAVA_OPTS="${JAVA_OPTS} ${OPTS}" - export ANT_OPTS="${ANT_OPTS} ${OPTS}" @@ -9,12 +10,12 @@ language: java jdk: - oraclejdk8 - - oraclejdk7 +# - oraclejdk7 # - oraclejdk6 # - openjdk8 - openjdk7 - - openjdk6 +# - openjdk6 env: - TEST_SUITE=run_tests @@ -27,4 +28,3 @@ env: # - TEST_SUITE=sorts script: "ant $TEST_SUITE" - diff --git a/README.md b/README.md index 060ebde8..459c4d35 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,7 @@ This is a collection of algorithms and data structures which I've implement over * [Suffix Trie [backed by a Trie]](src/com/jwetherell/algorithms/data_structures/SuffixTrie.java) * [Ternary Search Tree](src/com/jwetherell/algorithms/data_structures/TernarySearchTree.java) * [Treap](src/com/jwetherell/algorithms/data_structures/Treap.java) +* [Tree](src/com/jwetherell/algorithms/data_structures/Tree.java) * [Tree Map (associative array) [backed by an AVL Tree]](src/com/jwetherell/algorithms/data_structures/TreeMap.java) * [Trie](src/com/jwetherell/algorithms/data_structures/Trie.java) * [Trie Map (associative array) [backed by a Trie]](src/com/jwetherell/algorithms/data_structures/TrieMap.java) @@ -156,6 +157,8 @@ This is a collection of algorithms and data structures which I've implement over * [Edmonds Karp](src/com/jwetherell/algorithms/graph/EdmondsKarp.java) * Matching - [Turbo Matching](src/com/jwetherell/algorithms/graph/TurboMatching.java) +* [Lowest common ancestor in tree](src/com/jwetherell/algorithms/data_structures/Tree.java) + ## Search * Get index of value in array diff --git a/src/com/jwetherell/algorithms/data_structures/Tree.java b/src/com/jwetherell/algorithms/data_structures/Tree.java new file mode 100644 index 00000000..dd684f0b --- /dev/null +++ b/src/com/jwetherell/algorithms/data_structures/Tree.java @@ -0,0 +1,135 @@ +package com.jwetherell.algorithms.data_structures; + +import java.util.ArrayList; + +/** + * Structure for storing rooted tree which allows to find lowest common ancestor. + * + * @param type of value stored in nodes. + */ +public class Tree { + private T value = null; + private int depth = 0; + private final ArrayList> ancestors = new ArrayList<>(); + + /** + * Exception which can be thrown by lowestCommonAncestor function if two + * nodes are in different trees. + * + */ + public static class NodesNotInSameTreeException extends Exception {} + + /** + * Finds lower common ancestor of two nodes. + * + * Complexity O(log n) where n is the height of the tree. + * + * @param node1 first node + * @param node2 second node + * @return lower common ancestor + * @throws NodesNotInSameTreeException if nodes don't have common root + */ + public static Tree lowestCommonAncestor(Tree node1, Tree node2) throws NodesNotInSameTreeException { + if(node1 == node2) return node1; + else if(node1.depth < node2.depth) return lowestCommonAncestor(node2, node1); + else if(node1.depth > node2.depth) { + int diff = node1.depth - node2.depth; + int jump = 0; + while(diff > 0) { + if(diff % 2 == 1) + node1 = node1.ancestors.get(jump); + jump++; + diff /= 2; + } + return lowestCommonAncestor(node1, node2); + } + else { + try { + int step = 0; + while(1<<(step+1) <= node1.depth) step++; + while(step >= 0) { + if(step < node1.ancestors.size() && node1.ancestors.get(step) != node2.ancestors.get(step)) { + node1 = node1.ancestors.get(step); + node2 = node2.ancestors.get(step); + } + step--; + } + return node1.ancestors.get(0); + } catch (Exception e) { + throw new NodesNotInSameTreeException(); + } + + } + + } + + /** + * Creates tree with root only. + * + */ + public Tree() { + + } + + /** + * Cretes tree with root (storing value) only. + * + * @param value value to be stored in root + */ + public Tree(T value) { + this.value = value; + } + + private Tree(Tree parent) { + this.ancestors.add(parent); + this.depth = parent.depth + 1; + int dist = 0; + while(true) { + try { + this.ancestors.add(this.ancestors.get(dist).ancestors.get(dist)); + dist++; + } catch (Exception e){ + break; + } + } + } + + public Tree setValue(T value) { + this.value = value; + return this; + } + + /** + * Creates new child for this node and returns it. + * + * Complexity O(log depth) + * + * @return added child + */ + public Tree addChild() { + return new Tree<>(this); + } + + /** + * Creates new child (storing value) for this node and returns it. + * + * Complexity O(log depth) + * + * @param value value to be stored in new child + * @return added child + */ + public Tree addChild(T value) { + return addChild().setValue(value); + } + + /** + * Returns value stored in node. + * + * @return node's value. + */ + public T getValue() { + return value; + } + + +} diff --git a/test/com/jwetherell/algorithms/data_structures/TreeTest.java b/test/com/jwetherell/algorithms/data_structures/TreeTest.java new file mode 100644 index 00000000..83283a82 --- /dev/null +++ b/test/com/jwetherell/algorithms/data_structures/TreeTest.java @@ -0,0 +1,43 @@ +package com.jwetherell.algorithms.data_structures; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class TreeTest { + + @Test + public void largeTreeTest() throws Tree.NodesNotInSameTreeException { + Tree root = new Tree<>(); + Tree left = root.addChild(); + Tree middle = root.addChild(); + Tree right = root.addChild(); + + //long path + Tree v = left; + for(int i = 0; i<1000; i++) + v = v.addChild(); + Tree leftRight = left.addChild(); + + assertEquals(Tree.lowestCommonAncestor(v, leftRight), left); + + for(int i = 0; i<2000; i++) { + leftRight = leftRight.addChild(); + + assertEquals(Tree.lowestCommonAncestor(v, leftRight), left); + } + + assertEquals(Tree.lowestCommonAncestor(middle, right), root); + assertEquals(Tree.lowestCommonAncestor(root, right), root); + assertEquals(Tree.lowestCommonAncestor(root, root), root); + + Tree root2 = new Tree<>(); + boolean thrownException = false; + try { + Tree.lowestCommonAncestor(v, root2); + } catch (Tree.NodesNotInSameTreeException e) { + thrownException = true; + } + assertTrue(thrownException); + } +} \ No newline at end of file From ce10dd9d97fb983bde0ad67b4249c54c99654847 Mon Sep 17 00:00:00 2001 From: Szymon Stankiewicz Date: Tue, 5 Sep 2017 21:59:23 +0200 Subject: [PATCH 47/88] Renamed Tree to RootedTree and added 'contains' and 'find' methods to RootedTree --- .../{Tree.java => RootedTree.java} | 52 +++++++++++++++---- .../data_structures/RootedTreeTest.java | 50 ++++++++++++++++++ .../algorithms/data_structures/TreeTest.java | 43 --------------- 3 files changed, 92 insertions(+), 53 deletions(-) rename src/com/jwetherell/algorithms/data_structures/{Tree.java => RootedTree.java} (67%) create mode 100644 test/com/jwetherell/algorithms/data_structures/RootedTreeTest.java delete mode 100644 test/com/jwetherell/algorithms/data_structures/TreeTest.java diff --git a/src/com/jwetherell/algorithms/data_structures/Tree.java b/src/com/jwetherell/algorithms/data_structures/RootedTree.java similarity index 67% rename from src/com/jwetherell/algorithms/data_structures/Tree.java rename to src/com/jwetherell/algorithms/data_structures/RootedTree.java index dd684f0b..76ec95d2 100644 --- a/src/com/jwetherell/algorithms/data_structures/Tree.java +++ b/src/com/jwetherell/algorithms/data_structures/RootedTree.java @@ -7,10 +7,11 @@ * * @param type of value stored in nodes. */ -public class Tree { +public class RootedTree { private T value = null; private int depth = 0; - private final ArrayList> ancestors = new ArrayList<>(); + private final ArrayList> ancestors = new ArrayList<>(); + private final ArrayList> children = new ArrayList<>(); /** * Exception which can be thrown by lowestCommonAncestor function if two @@ -29,7 +30,7 @@ public static class NodesNotInSameTreeException extends Exception {} * @return lower common ancestor * @throws NodesNotInSameTreeException if nodes don't have common root */ - public static Tree lowestCommonAncestor(Tree node1, Tree node2) throws NodesNotInSameTreeException { + public static RootedTree lowestCommonAncestor(RootedTree node1, RootedTree node2) throws NodesNotInSameTreeException { if(node1 == node2) return node1; else if(node1.depth < node2.depth) return lowestCommonAncestor(node2, node1); else if(node1.depth > node2.depth) { @@ -67,7 +68,7 @@ else if(node1.depth > node2.depth) { * Creates tree with root only. * */ - public Tree() { + public RootedTree() { } @@ -76,11 +77,12 @@ public Tree() { * * @param value value to be stored in root */ - public Tree(T value) { + public RootedTree(T value) { this.value = value; } - private Tree(Tree parent) { + private RootedTree(RootedTree parent) { + parent.children.add(this); this.ancestors.add(parent); this.depth = parent.depth + 1; int dist = 0; @@ -94,7 +96,7 @@ private Tree(Tree parent) { } } - public Tree setValue(T value) { + public RootedTree setValue(T value) { this.value = value; return this; } @@ -106,8 +108,8 @@ public Tree setValue(T value) { * * @return added child */ - public Tree addChild() { - return new Tree<>(this); + public RootedTree addChild() { + return new RootedTree<>(this); } /** @@ -118,7 +120,7 @@ public Tree addChild() { * @param value value to be stored in new child * @return added child */ - public Tree addChild(T value) { + public RootedTree addChild(T value) { return addChild().setValue(value); } @@ -131,5 +133,35 @@ public T getValue() { return value; } + /** + * Finds subtree with given value in the root. + * + * @param value value to be find + * @return subtree with given value in the root + */ + public RootedTree find(T value) { + if(this.value == null) { + if(value == null) + return this; + } + else if(this.value.equals(value)) + return this; + for(RootedTree child: children) { + RootedTree res = child.find(value); + if(res != null) + return res; + } + return null; + } + + /** + * Returns true if tree contains a node with given value + * + * @param value to be checked + * @return true if tree contains node with given value, false otherwise + */ + public boolean contains(T value) { + return find(value) != null; + } } diff --git a/test/com/jwetherell/algorithms/data_structures/RootedTreeTest.java b/test/com/jwetherell/algorithms/data_structures/RootedTreeTest.java new file mode 100644 index 00000000..bfed080e --- /dev/null +++ b/test/com/jwetherell/algorithms/data_structures/RootedTreeTest.java @@ -0,0 +1,50 @@ +package com.jwetherell.algorithms.data_structures; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class RootedTreeTest { + + @Test + public void largeTreeTest() throws RootedTree.NodesNotInSameTreeException { + RootedTree root = new RootedTree<>(); + RootedTree left = root.addChild(); + RootedTree middle = root.addChild(); + RootedTree right = root.addChild(); + + //long path + RootedTree v = left; + for(int i = 0; i<1000; i++) + v = v.addChild(); + RootedTree leftRight = left.addChild(); + + assertEquals(RootedTree.lowestCommonAncestor(v, leftRight), left); + + for(int i = 0; i<2000; i++) { + leftRight = leftRight.addChild(); + + assertEquals(RootedTree.lowestCommonAncestor(v, leftRight), left); + } + + assertEquals(RootedTree.lowestCommonAncestor(middle, right), root); + assertEquals(RootedTree.lowestCommonAncestor(root, right), root); + assertEquals(RootedTree.lowestCommonAncestor(root, root), root); + + RootedTree root2 = new RootedTree<>(); + boolean thrownException = false; + try { + RootedTree.lowestCommonAncestor(v, root2); + } catch (RootedTree.NodesNotInSameTreeException e) { + thrownException = true; + } + assertTrue(thrownException); + + RootedTree deepChild = v.addChild(101); + assertEquals(deepChild, root.find(101)); + assertTrue(root.contains(101)); + + assertNull(root.find(102)); + assertFalse(root.contains(102)); + } +} \ No newline at end of file diff --git a/test/com/jwetherell/algorithms/data_structures/TreeTest.java b/test/com/jwetherell/algorithms/data_structures/TreeTest.java deleted file mode 100644 index 83283a82..00000000 --- a/test/com/jwetherell/algorithms/data_structures/TreeTest.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.jwetherell.algorithms.data_structures; - -import org.junit.Test; - -import static org.junit.Assert.*; - -public class TreeTest { - - @Test - public void largeTreeTest() throws Tree.NodesNotInSameTreeException { - Tree root = new Tree<>(); - Tree left = root.addChild(); - Tree middle = root.addChild(); - Tree right = root.addChild(); - - //long path - Tree v = left; - for(int i = 0; i<1000; i++) - v = v.addChild(); - Tree leftRight = left.addChild(); - - assertEquals(Tree.lowestCommonAncestor(v, leftRight), left); - - for(int i = 0; i<2000; i++) { - leftRight = leftRight.addChild(); - - assertEquals(Tree.lowestCommonAncestor(v, leftRight), left); - } - - assertEquals(Tree.lowestCommonAncestor(middle, right), root); - assertEquals(Tree.lowestCommonAncestor(root, right), root); - assertEquals(Tree.lowestCommonAncestor(root, root), root); - - Tree root2 = new Tree<>(); - boolean thrownException = false; - try { - Tree.lowestCommonAncestor(v, root2); - } catch (Tree.NodesNotInSameTreeException e) { - thrownException = true; - } - assertTrue(thrownException); - } -} \ No newline at end of file From 0863f2493ce5e2c7d90f7396ff48cb66a6a9ac13 Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Wed, 20 Sep 2017 10:01:10 -0400 Subject: [PATCH 48/88] Update .travis.yml Add open jdk 6 & 7 --- .travis.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 58364da4..337f7d7e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,13 +9,15 @@ before_script: language: java jdk: - - oraclejdk8 +# - oraclejdk9 +# - oraclejdk8 # - oraclejdk7 # - oraclejdk6 -# - openjdk8 +# - openjdk9 + - openjdk8 - openjdk7 -# - openjdk6 + - openjdk6 env: - TEST_SUITE=run_tests From b6464f5def13cca8ea3a86f277fb00e06a1a59d0 Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Wed, 20 Sep 2017 10:07:15 -0400 Subject: [PATCH 49/88] Update .travis.yml --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index 337f7d7e..59d39462 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,11 @@ before_script: - echo $JAVA_OPTS - echo $ANT_OPTS +addons: + apt: + packages: + - openjdk-6-jdk + language: java jdk: From 75661cb0fddf827d3e454139abf07a6051ea6caf Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Wed, 20 Sep 2017 10:19:40 -0400 Subject: [PATCH 50/88] Code cleanup in Interval sum and rooted tree --- .../data_structures/IntervalSumArray.java | 33 ++++++------ .../data_structures/RootedTree.java | 50 +++++++++++-------- .../data_structures/SuffixArray.java | 1 + 3 files changed, 48 insertions(+), 36 deletions(-) diff --git a/src/com/jwetherell/algorithms/data_structures/IntervalSumArray.java b/src/com/jwetherell/algorithms/data_structures/IntervalSumArray.java index 4f567ef5..cbbd65e0 100644 --- a/src/com/jwetherell/algorithms/data_structures/IntervalSumArray.java +++ b/src/com/jwetherell/algorithms/data_structures/IntervalSumArray.java @@ -1,15 +1,19 @@ package com.jwetherell.algorithms.data_structures; +import java.util.List; +import java.util.ArrayList; /** * Implementation of array holding integer values which allows to count sum of elements in given * interval in O(log n) complexity. - * + *
* @author Szymon Stankiewicz + * @author Justin Wetherell */ public class IntervalSumArray { - private List.ArrayList values = new List.ArrayList<>(); - private List.ArrayList prefSums = new List.ArrayList<>(); + + private List values = new ArrayList(); + private List prefSums = new ArrayList(); /** * Creates empty IntervalSumArray @@ -27,8 +31,7 @@ public IntervalSumArray() { * @param size size of IntervalSumArray */ public IntervalSumArray(int size) { - this(); - for(int i = 0; i values) { - this(); - for(Integer v: values) + for (Integer v: values) add(v); } private static int greatestPowerOfTwoDividing(int x) { - return x&(-x); + return x & (-x); } private static int successor(int x) { @@ -75,7 +77,7 @@ public int size() { */ public void add(int val) { values.add(val); - for(int i = 1; i= size()) throw new IndexOutOfBoundsException(); + if (index < 0 || index >= size()) + throw new IndexOutOfBoundsException(); index++; int diff = val - values.get(index); values.set(index, val); - while(index <= size()) { + while (index <= size()) { int oldPrefSum = prefSums.get(index); prefSums.set(index, oldPrefSum + diff); index = successor(index); @@ -121,10 +124,11 @@ public int get(int index) { * @return sum of values in interval */ public int sum(int end) { - if(end < 0 || end >= size()) throw new IndexOutOfBoundsException(); + if (end < 0 || end >= size()) + throw new IndexOutOfBoundsException(); end++; int s = 0; - while(end > 0) { + while (end > 0) { s += prefSums.get(end); end = predecessor(end); } @@ -152,7 +156,8 @@ public int sum() { * @return sum of values in interval */ public int sum(int start, int end) { - if(start > end) throw new IllegalArgumentException("Start must be less then end"); + if (start > end) + throw new IllegalArgumentException("Start must be less then end"); int startPrefSum = start == 0 ? 0 : sum(start-1); int endPrefSum = sum(end); return endPrefSum - startPrefSum; diff --git a/src/com/jwetherell/algorithms/data_structures/RootedTree.java b/src/com/jwetherell/algorithms/data_structures/RootedTree.java index 76ec95d2..3008d14e 100644 --- a/src/com/jwetherell/algorithms/data_structures/RootedTree.java +++ b/src/com/jwetherell/algorithms/data_structures/RootedTree.java @@ -1,24 +1,32 @@ package com.jwetherell.algorithms.data_structures; +import java.util.List; import java.util.ArrayList; /** * Structure for storing rooted tree which allows to find lowest common ancestor. - * + *

* @param type of value stored in nodes. + *
+ * @author Szymon Stankiewicz + * @author Justin Wetherell */ public class RootedTree { + + private final List> ancestors = new ArrayList>(); + private final List> children = new ArrayList>(); + private T value = null; private int depth = 0; - private final ArrayList> ancestors = new ArrayList<>(); - private final ArrayList> children = new ArrayList<>(); /** * Exception which can be thrown by lowestCommonAncestor function if two * nodes are in different trees. * */ - public static class NodesNotInSameTreeException extends Exception {} + public static class NodesNotInSameTreeException extends Exception { + private static final long serialVersionUID = -5366787886097250564L; + } /** * Finds lower common ancestor of two nodes. @@ -31,9 +39,11 @@ public static class NodesNotInSameTreeException extends Exception {} * @throws NodesNotInSameTreeException if nodes don't have common root */ public static RootedTree lowestCommonAncestor(RootedTree node1, RootedTree node2) throws NodesNotInSameTreeException { - if(node1 == node2) return node1; - else if(node1.depth < node2.depth) return lowestCommonAncestor(node2, node1); - else if(node1.depth > node2.depth) { + if (node1 == node2) + return node1; + else if (node1.depth < node2.depth) + return lowestCommonAncestor(node2, node1); + else if (node1.depth > node2.depth) { int diff = node1.depth - node2.depth; int jump = 0; while(diff > 0) { @@ -43,12 +53,12 @@ else if(node1.depth > node2.depth) { diff /= 2; } return lowestCommonAncestor(node1, node2); - } - else { + } else { try { int step = 0; - while(1<<(step+1) <= node1.depth) step++; - while(step >= 0) { + while (1<<(step+1) <= node1.depth) + step++; + while (step >= 0) { if(step < node1.ancestors.size() && node1.ancestors.get(step) != node2.ancestors.get(step)) { node1 = node1.ancestors.get(step); node2 = node2.ancestors.get(step); @@ -61,16 +71,13 @@ else if(node1.depth > node2.depth) { } } - } /** * Creates tree with root only. * */ - public RootedTree() { - - } + public RootedTree() { } /** * Cretes tree with root (storing value) only. @@ -109,7 +116,7 @@ public RootedTree setValue(T value) { * @return added child */ public RootedTree addChild() { - return new RootedTree<>(this); + return new RootedTree(this); } /** @@ -140,15 +147,15 @@ public T getValue() { * @return subtree with given value in the root */ public RootedTree find(T value) { - if(this.value == null) { - if(value == null) + if (this.value == null) { + if (value == null) return this; } - else if(this.value.equals(value)) + else if (this.value.equals(value)) return this; - for(RootedTree child: children) { + for (RootedTree child: children) { RootedTree res = child.find(value); - if(res != null) + if (res != null) return res; } return null; @@ -163,5 +170,4 @@ else if(this.value.equals(value)) public boolean contains(T value) { return find(value) != null; } - } diff --git a/src/com/jwetherell/algorithms/data_structures/SuffixArray.java b/src/com/jwetherell/algorithms/data_structures/SuffixArray.java index 2d01ed9f..640754f0 100644 --- a/src/com/jwetherell/algorithms/data_structures/SuffixArray.java +++ b/src/com/jwetherell/algorithms/data_structures/SuffixArray.java @@ -165,6 +165,7 @@ private String buildStringWithEndChar(CharSequence sequence) { } private class KMRsWithIndex{ + Integer beginKMR; Integer endKMR; Integer index; From 98c93943ef57fb24b3fd820503ddc6b535318bad Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Wed, 20 Sep 2017 10:19:59 -0400 Subject: [PATCH 51/88] Code cleanup in Interval sum and rooted tree --- .../data_structures/IntervalSumArrayTest.java | 38 +++++++++---------- .../data_structures/RootedTreeTest.java | 21 +++++----- 2 files changed, 29 insertions(+), 30 deletions(-) diff --git a/test/com/jwetherell/algorithms/data_structures/IntervalSumArrayTest.java b/test/com/jwetherell/algorithms/data_structures/IntervalSumArrayTest.java index 0af23a19..1a5de6f8 100644 --- a/test/com/jwetherell/algorithms/data_structures/IntervalSumArrayTest.java +++ b/test/com/jwetherell/algorithms/data_structures/IntervalSumArrayTest.java @@ -1,44 +1,45 @@ package com.jwetherell.algorithms.data_structures; -import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.List; import java.util.Random; -import static org.junit.Assert.*; +import org.junit.Test; public class IntervalSumArrayTest { @Test public void properSumAllElementsTest() { - IntervalSumArray sub = new IntervalSumArray(); - for(int i = 0; i<=100; i++) + final IntervalSumArray sub = new IntervalSumArray(); + for (int i = 0; i<=100; i++) sub.add(i); - for(int i = 0; i<=100; i++) + for (int i = 0; i<=100; i++) assertEquals(i*(i+1)/2, sub.sum(i)); assertEquals(100*101/2, sub.sum()); } @Test public void randomGeneratedTest() { - Random generator = new Random(42); - List list = new ArrayList<>(); - for(int i = 0; i<=100; i++) + final Random generator = new Random(42); + final List list = new ArrayList(); + for (int i = 0; i<=100; i++) list.add(i); - IntervalSumArray sum = new IntervalSumArray(list); - for(int i = 0; i<1000000; i++) { - int pos = generator.nextInt(100); - int val = generator.nextInt(2000000) - 1000000; + final IntervalSumArray sum = new IntervalSumArray(list); + for (int i = 0; i<1000000; i++) { + final int pos = generator.nextInt(100); + final int val = generator.nextInt(2000000) - 1000000; sum.set(pos, val); list.set(pos, val); assertEquals(val, sum.get(pos)); } int s = 0; - List prefSum = new ArrayList<>(); + final List prefSum = new ArrayList(); prefSum.add(s); - for(Integer val: list) { + for (Integer val: list) { s += val; prefSum.add(s); } @@ -52,7 +53,7 @@ public void randomGeneratedTest() { @Test public void setIndexOutOfRangeTest() { - IntervalSumArray sum = new IntervalSumArray(100); + final IntervalSumArray sum = new IntervalSumArray(100); boolean thrown = false; try { sum.set(101, 10); @@ -64,7 +65,7 @@ public void setIndexOutOfRangeTest() { @Test public void sumIndexOutOfRangeTest() { - IntervalSumArray sum = new IntervalSumArray(100); + final IntervalSumArray sum = new IntervalSumArray(100); boolean thrown = false; try { sum.sum(101); @@ -76,7 +77,7 @@ public void sumIndexOutOfRangeTest() { @Test public void endBeforeStartTest() { - IntervalSumArray sum = new IntervalSumArray(100); + final IntervalSumArray sum = new IntervalSumArray(100); boolean thrown = false; try { sum.sum(101, 100); @@ -85,5 +86,4 @@ public void endBeforeStartTest() { } assertTrue(thrown); } - -} \ No newline at end of file +} diff --git a/test/com/jwetherell/algorithms/data_structures/RootedTreeTest.java b/test/com/jwetherell/algorithms/data_structures/RootedTreeTest.java index bfed080e..cd210dc7 100644 --- a/test/com/jwetherell/algorithms/data_structures/RootedTreeTest.java +++ b/test/com/jwetherell/algorithms/data_structures/RootedTreeTest.java @@ -8,22 +8,21 @@ public class RootedTreeTest { @Test public void largeTreeTest() throws RootedTree.NodesNotInSameTreeException { - RootedTree root = new RootedTree<>(); - RootedTree left = root.addChild(); - RootedTree middle = root.addChild(); - RootedTree right = root.addChild(); + + final RootedTree root = new RootedTree(); + final RootedTree left = root.addChild(); + final RootedTree middle = root.addChild(); + final RootedTree right = root.addChild(); //long path RootedTree v = left; - for(int i = 0; i<1000; i++) + for (int i = 0; i<1000; i++) v = v.addChild(); RootedTree leftRight = left.addChild(); - assertEquals(RootedTree.lowestCommonAncestor(v, leftRight), left); - for(int i = 0; i<2000; i++) { + for (int i = 0; i<2000; i++) { leftRight = leftRight.addChild(); - assertEquals(RootedTree.lowestCommonAncestor(v, leftRight), left); } @@ -31,7 +30,7 @@ public void largeTreeTest() throws RootedTree.NodesNotInSameTreeException { assertEquals(RootedTree.lowestCommonAncestor(root, right), root); assertEquals(RootedTree.lowestCommonAncestor(root, root), root); - RootedTree root2 = new RootedTree<>(); + final RootedTree root2 = new RootedTree(); boolean thrownException = false; try { RootedTree.lowestCommonAncestor(v, root2); @@ -40,11 +39,11 @@ public void largeTreeTest() throws RootedTree.NodesNotInSameTreeException { } assertTrue(thrownException); - RootedTree deepChild = v.addChild(101); + final RootedTree deepChild = v.addChild(101); assertEquals(deepChild, root.find(101)); assertTrue(root.contains(101)); assertNull(root.find(102)); assertFalse(root.contains(102)); } -} \ No newline at end of file +} From c8680af4ccb2fe322ebbbe20983c41d56806fd58 Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Wed, 20 Sep 2017 10:25:52 -0400 Subject: [PATCH 52/88] Update .travis.yml --- .travis.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 59d39462..bf141759 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,12 +14,12 @@ addons: language: java jdk: -# - oraclejdk9 -# - oraclejdk8 -# - oraclejdk7 -# - oraclejdk6 + - oraclejdk9 + - oraclejdk8 + - oraclejdk7 + - oraclejdk6 -# - openjdk9 + - openjdk9 - openjdk8 - openjdk7 - openjdk6 From 39d4f2d41db044f9037703c5b9ec34f97dc54598 Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Wed, 20 Sep 2017 10:29:53 -0400 Subject: [PATCH 53/88] Update .travis.yml --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index bf141759..e2324a51 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,10 +16,10 @@ language: java jdk: - oraclejdk9 - oraclejdk8 - - oraclejdk7 - - oraclejdk6 +# - oraclejdk7 +# - oraclejdk6 - - openjdk9 +# - openjdk9 - openjdk8 - openjdk7 - openjdk6 From c00a62e1742e726017da617e577f824f5f261c9a Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Wed, 20 Sep 2017 10:55:54 -0400 Subject: [PATCH 54/88] Code cleanup in Lowest Common Ancestor --- .../data_structures/LowestCommonAncestor.java | 175 ++++++++++++++++++ .../data_structures/RootedTree.java | 173 ----------------- .../data_structures/RootedTreeTest.java | 49 ----- .../{ => test}/IntervalSumArrayTest.java | 8 +- .../test/LowestCommonAncestorTest.java | 56 ++++++ 5 files changed, 236 insertions(+), 225 deletions(-) create mode 100644 src/com/jwetherell/algorithms/data_structures/LowestCommonAncestor.java delete mode 100644 src/com/jwetherell/algorithms/data_structures/RootedTree.java delete mode 100644 test/com/jwetherell/algorithms/data_structures/RootedTreeTest.java rename test/com/jwetherell/algorithms/data_structures/{ => test}/IntervalSumArrayTest.java (92%) create mode 100644 test/com/jwetherell/algorithms/data_structures/test/LowestCommonAncestorTest.java diff --git a/src/com/jwetherell/algorithms/data_structures/LowestCommonAncestor.java b/src/com/jwetherell/algorithms/data_structures/LowestCommonAncestor.java new file mode 100644 index 00000000..f6b4ef66 --- /dev/null +++ b/src/com/jwetherell/algorithms/data_structures/LowestCommonAncestor.java @@ -0,0 +1,175 @@ +package com.jwetherell.algorithms.data_structures; + +import java.util.ArrayList; +import java.util.List; + +/** + * Structure for storing rooted tree which allows to find lowest common ancestor. + *

+ * @param type of value stored in nodes. + *
+ * @author Szymon Stankiewicz + * @author Justin Wetherell + */ +public class LowestCommonAncestor { + + /** + * Exception which can be thrown by lowestCommonAncestor function if two + * nodes are in different trees. + * + */ + public static class NodesNotInSameTreeException extends Exception { + private static final long serialVersionUID = -5366787886097250564L; + } + + /** + * Finds lower common ancestor of two nodes. + * + * Complexity O(log n) where n is the height of the tree. + * + * @param node1 first node + * @param node2 second node + * @return lower common ancestor + * @throws NodesNotInSameTreeException if nodes don't have common root + */ + public static RootedTree lowestCommonAncestor(RootedTree node1, RootedTree node2) throws NodesNotInSameTreeException { + if (node1 == node2) + return node1; + else if (node1.depth < node2.depth) + return lowestCommonAncestor(node2, node1); + else if (node1.depth > node2.depth) { + int diff = node1.depth - node2.depth; + int jump = 0; + while (diff > 0) { + if (diff % 2 == 1) + node1 = node1.ancestors.get(jump); + jump++; + diff /= 2; + } + return lowestCommonAncestor(node1, node2); + } else { + try { + int step = 0; + while (1<<(step+1) <= node1.depth) + step++; + while (step >= 0) { + if(step < node1.ancestors.size() && node1.ancestors.get(step) != node2.ancestors.get(step)) { + node1 = node1.ancestors.get(step); + node2 = node2.ancestors.get(step); + } + step--; + } + return node1.ancestors.get(0); + } catch (Exception e) { + throw new NodesNotInSameTreeException(); + } + + } + } + + public static final class RootedTree { + + private final List> ancestors = new ArrayList>(); + private final List> children = new ArrayList>(); + + private T value = null; + private int depth = 0; + + /** + * Creates tree with root only. + * + */ + public RootedTree() { } + + /** + * Creates tree with root (storing value) only. + * + * @param value value to be stored in root + */ + public RootedTree(T value) { + this.value = value; + } + + private RootedTree(RootedTree parent) { + parent.children.add(this); + this.ancestors.add(parent); + this.depth = parent.depth + 1; + int dist = 0; + while (true) { + try { + this.ancestors.add(this.ancestors.get(dist).ancestors.get(dist)); + dist++; + } catch (Exception e){ + break; + } + } + } + + public RootedTree setValue(T value) { + this.value = value; + return this; + } + + /** + * Creates new child for this node and returns it. + * + * Complexity O(log depth) + * + * @return added child + */ + public RootedTree addChild() { + return new RootedTree(this); + } + + /** + * Creates new child (storing value) for this node and returns it. + * + * Complexity O(log depth) + * + * @param value value to be stored in new child + * @return added child + */ + public RootedTree addChild(T value) { + return addChild().setValue(value); + } + + /** + * Returns value stored in node. + * + * @return node's value. + */ + public T getValue() { + return value; + } + + /** + * Finds subtree with given value in the root. + * + * @param value value to be find + * @return subtree with given value in the root + */ + public RootedTree find(T value) { + if (this.value == null) { + if (value == null) + return this; + } else if (this.value.equals(value)) + return this; + for (RootedTree child: children) { + final RootedTree res = child.find(value); + if (res != null) + return res; + } + return null; + } + + /** + * Returns true if tree contains a node with given value + * + * @param value to be checked + * @return true if tree contains node with given value, false otherwise + */ + public boolean contains(T value) { + return find(value) != null; + } + } +} diff --git a/src/com/jwetherell/algorithms/data_structures/RootedTree.java b/src/com/jwetherell/algorithms/data_structures/RootedTree.java deleted file mode 100644 index 3008d14e..00000000 --- a/src/com/jwetherell/algorithms/data_structures/RootedTree.java +++ /dev/null @@ -1,173 +0,0 @@ -package com.jwetherell.algorithms.data_structures; - -import java.util.List; -import java.util.ArrayList; - -/** - * Structure for storing rooted tree which allows to find lowest common ancestor. - *

- * @param type of value stored in nodes. - *
- * @author Szymon Stankiewicz - * @author Justin Wetherell - */ -public class RootedTree { - - private final List> ancestors = new ArrayList>(); - private final List> children = new ArrayList>(); - - private T value = null; - private int depth = 0; - - /** - * Exception which can be thrown by lowestCommonAncestor function if two - * nodes are in different trees. - * - */ - public static class NodesNotInSameTreeException extends Exception { - private static final long serialVersionUID = -5366787886097250564L; - } - - /** - * Finds lower common ancestor of two nodes. - * - * Complexity O(log n) where n is the height of the tree. - * - * @param node1 first node - * @param node2 second node - * @return lower common ancestor - * @throws NodesNotInSameTreeException if nodes don't have common root - */ - public static RootedTree lowestCommonAncestor(RootedTree node1, RootedTree node2) throws NodesNotInSameTreeException { - if (node1 == node2) - return node1; - else if (node1.depth < node2.depth) - return lowestCommonAncestor(node2, node1); - else if (node1.depth > node2.depth) { - int diff = node1.depth - node2.depth; - int jump = 0; - while(diff > 0) { - if(diff % 2 == 1) - node1 = node1.ancestors.get(jump); - jump++; - diff /= 2; - } - return lowestCommonAncestor(node1, node2); - } else { - try { - int step = 0; - while (1<<(step+1) <= node1.depth) - step++; - while (step >= 0) { - if(step < node1.ancestors.size() && node1.ancestors.get(step) != node2.ancestors.get(step)) { - node1 = node1.ancestors.get(step); - node2 = node2.ancestors.get(step); - } - step--; - } - return node1.ancestors.get(0); - } catch (Exception e) { - throw new NodesNotInSameTreeException(); - } - - } - } - - /** - * Creates tree with root only. - * - */ - public RootedTree() { } - - /** - * Cretes tree with root (storing value) only. - * - * @param value value to be stored in root - */ - public RootedTree(T value) { - this.value = value; - } - - private RootedTree(RootedTree parent) { - parent.children.add(this); - this.ancestors.add(parent); - this.depth = parent.depth + 1; - int dist = 0; - while(true) { - try { - this.ancestors.add(this.ancestors.get(dist).ancestors.get(dist)); - dist++; - } catch (Exception e){ - break; - } - } - } - - public RootedTree setValue(T value) { - this.value = value; - return this; - } - - /** - * Creates new child for this node and returns it. - * - * Complexity O(log depth) - * - * @return added child - */ - public RootedTree addChild() { - return new RootedTree(this); - } - - /** - * Creates new child (storing value) for this node and returns it. - * - * Complexity O(log depth) - * - * @param value value to be stored in new child - * @return added child - */ - public RootedTree addChild(T value) { - return addChild().setValue(value); - } - - /** - * Returns value stored in node. - * - * @return node's value. - */ - public T getValue() { - return value; - } - - /** - * Finds subtree with given value in the root. - * - * @param value value to be find - * @return subtree with given value in the root - */ - public RootedTree find(T value) { - if (this.value == null) { - if (value == null) - return this; - } - else if (this.value.equals(value)) - return this; - for (RootedTree child: children) { - RootedTree res = child.find(value); - if (res != null) - return res; - } - return null; - } - - /** - * Returns true if tree contains a node with given value - * - * @param value to be checked - * @return true if tree contains node with given value, false otherwise - */ - public boolean contains(T value) { - return find(value) != null; - } -} diff --git a/test/com/jwetherell/algorithms/data_structures/RootedTreeTest.java b/test/com/jwetherell/algorithms/data_structures/RootedTreeTest.java deleted file mode 100644 index cd210dc7..00000000 --- a/test/com/jwetherell/algorithms/data_structures/RootedTreeTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.jwetherell.algorithms.data_structures; - -import org.junit.Test; - -import static org.junit.Assert.*; - -public class RootedTreeTest { - - @Test - public void largeTreeTest() throws RootedTree.NodesNotInSameTreeException { - - final RootedTree root = new RootedTree(); - final RootedTree left = root.addChild(); - final RootedTree middle = root.addChild(); - final RootedTree right = root.addChild(); - - //long path - RootedTree v = left; - for (int i = 0; i<1000; i++) - v = v.addChild(); - RootedTree leftRight = left.addChild(); - assertEquals(RootedTree.lowestCommonAncestor(v, leftRight), left); - - for (int i = 0; i<2000; i++) { - leftRight = leftRight.addChild(); - assertEquals(RootedTree.lowestCommonAncestor(v, leftRight), left); - } - - assertEquals(RootedTree.lowestCommonAncestor(middle, right), root); - assertEquals(RootedTree.lowestCommonAncestor(root, right), root); - assertEquals(RootedTree.lowestCommonAncestor(root, root), root); - - final RootedTree root2 = new RootedTree(); - boolean thrownException = false; - try { - RootedTree.lowestCommonAncestor(v, root2); - } catch (RootedTree.NodesNotInSameTreeException e) { - thrownException = true; - } - assertTrue(thrownException); - - final RootedTree deepChild = v.addChild(101); - assertEquals(deepChild, root.find(101)); - assertTrue(root.contains(101)); - - assertNull(root.find(102)); - assertFalse(root.contains(102)); - } -} diff --git a/test/com/jwetherell/algorithms/data_structures/IntervalSumArrayTest.java b/test/com/jwetherell/algorithms/data_structures/test/IntervalSumArrayTest.java similarity index 92% rename from test/com/jwetherell/algorithms/data_structures/IntervalSumArrayTest.java rename to test/com/jwetherell/algorithms/data_structures/test/IntervalSumArrayTest.java index 1a5de6f8..35770271 100644 --- a/test/com/jwetherell/algorithms/data_structures/IntervalSumArrayTest.java +++ b/test/com/jwetherell/algorithms/data_structures/test/IntervalSumArrayTest.java @@ -1,4 +1,4 @@ -package com.jwetherell.algorithms.data_structures; +package com.jwetherell.algorithms.data_structures.test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -9,6 +9,8 @@ import org.junit.Test; +import com.jwetherell.algorithms.data_structures.IntervalSumArray; + public class IntervalSumArrayTest { @Test @@ -44,8 +46,8 @@ public void randomGeneratedTest() { prefSum.add(s); } - for(int i = 0; i<=100; i++) { - for(int j = i; j<=100; j++) { + for (int i = 0; i<100; i++) { + for (int j = i; j<100; j++) { assertEquals(prefSum.get(j+1) - prefSum.get(i), sum.sum(i, j)); } } diff --git a/test/com/jwetherell/algorithms/data_structures/test/LowestCommonAncestorTest.java b/test/com/jwetherell/algorithms/data_structures/test/LowestCommonAncestorTest.java new file mode 100644 index 00000000..b8e43f5f --- /dev/null +++ b/test/com/jwetherell/algorithms/data_structures/test/LowestCommonAncestorTest.java @@ -0,0 +1,56 @@ +package com.jwetherell.algorithms.data_structures.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.jwetherell.algorithms.data_structures.LowestCommonAncestor; +import com.jwetherell.algorithms.data_structures.LowestCommonAncestor.NodesNotInSameTreeException; +import com.jwetherell.algorithms.data_structures.LowestCommonAncestor.RootedTree; + +public class LowestCommonAncestorTest { + + @Test + public void largeTreeTest() throws NodesNotInSameTreeException { + + final RootedTree root = new RootedTree(); + final RootedTree left = root.addChild(); + final RootedTree middle = root.addChild(); + final RootedTree right = root.addChild(); + + //long path + RootedTree v = left; + for (int i = 0; i<1000; i++) + v = v.addChild(); + RootedTree leftRight = left.addChild(); + assertEquals(LowestCommonAncestor.lowestCommonAncestor(v, leftRight), left); + + for (int i = 0; i<2000; i++) { + leftRight = leftRight.addChild(); + assertEquals(LowestCommonAncestor.lowestCommonAncestor(v, leftRight), left); + } + + assertEquals(LowestCommonAncestor.lowestCommonAncestor(middle, right), root); + assertEquals(LowestCommonAncestor.lowestCommonAncestor(root, right), root); + assertEquals(LowestCommonAncestor.lowestCommonAncestor(root, root), root); + + final RootedTree root2 = new RootedTree(); + boolean thrownException = false; + try { + LowestCommonAncestor.lowestCommonAncestor(v, root2); + } catch (NodesNotInSameTreeException e) { + thrownException = true; + } + assertTrue(thrownException); + + final RootedTree deepChild = v.addChild(101); + assertEquals(deepChild, root.find(101)); + assertTrue(root.contains(101)); + + assertNull(root.find(102)); + assertFalse(root.contains(102)); + } +} From b23f385b6531e0047dc4e91573939a6a799b439d Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Wed, 20 Sep 2017 14:10:49 -0400 Subject: [PATCH 55/88] Updated IntervalSum and LowestCommonAncestor --- ...IntervalSumArray.java => IntervalSum.java} | 8 ++--- .../data_structures/LowestCommonAncestor.java | 32 +++++++++---------- ...SumArrayTest.java => IntervalSumTest.java} | 14 ++++---- .../test/LowestCommonAncestorTest.java | 18 +++++------ 4 files changed, 36 insertions(+), 36 deletions(-) rename src/com/jwetherell/algorithms/data_structures/{IntervalSumArray.java => IntervalSum.java} (96%) rename test/com/jwetherell/algorithms/data_structures/test/{IntervalSumArrayTest.java => IntervalSumTest.java} (83%) diff --git a/src/com/jwetherell/algorithms/data_structures/IntervalSumArray.java b/src/com/jwetherell/algorithms/data_structures/IntervalSum.java similarity index 96% rename from src/com/jwetherell/algorithms/data_structures/IntervalSumArray.java rename to src/com/jwetherell/algorithms/data_structures/IntervalSum.java index cbbd65e0..b4c62f57 100644 --- a/src/com/jwetherell/algorithms/data_structures/IntervalSumArray.java +++ b/src/com/jwetherell/algorithms/data_structures/IntervalSum.java @@ -10,7 +10,7 @@ * @author Szymon Stankiewicz * @author Justin Wetherell */ -public class IntervalSumArray { +public class IntervalSum { private List values = new ArrayList(); private List prefSums = new ArrayList(); @@ -18,7 +18,7 @@ public class IntervalSumArray { /** * Creates empty IntervalSumArray */ - public IntervalSumArray() { + public IntervalSum() { values.add(0); prefSums.add(0); } @@ -30,7 +30,7 @@ public IntervalSumArray() { * * @param size size of IntervalSumArray */ - public IntervalSumArray(int size) { + public IntervalSum(int size) { for (int i = 0; i values) { + public IntervalSum(Iterable values) { for (Integer v: values) add(v); } diff --git a/src/com/jwetherell/algorithms/data_structures/LowestCommonAncestor.java b/src/com/jwetherell/algorithms/data_structures/LowestCommonAncestor.java index f6b4ef66..5d9f0bca 100644 --- a/src/com/jwetherell/algorithms/data_structures/LowestCommonAncestor.java +++ b/src/com/jwetherell/algorithms/data_structures/LowestCommonAncestor.java @@ -32,7 +32,7 @@ public static class NodesNotInSameTreeException extends Exception { * @return lower common ancestor * @throws NodesNotInSameTreeException if nodes don't have common root */ - public static RootedTree lowestCommonAncestor(RootedTree node1, RootedTree node2) throws NodesNotInSameTreeException { + public static TreeNode lowestCommonAncestor(TreeNode node1, TreeNode node2) throws NodesNotInSameTreeException { if (node1 == node2) return node1; else if (node1.depth < node2.depth) @@ -67,30 +67,30 @@ else if (node1.depth > node2.depth) { } } - public static final class RootedTree { + public static final class TreeNode { - private final List> ancestors = new ArrayList>(); - private final List> children = new ArrayList>(); + private final List> ancestors = new ArrayList>(); + private final List> children = new ArrayList>(); - private T value = null; - private int depth = 0; + private T value = null; + private int depth = 0; /** * Creates tree with root only. * */ - public RootedTree() { } + public TreeNode() { } /** * Creates tree with root (storing value) only. * * @param value value to be stored in root */ - public RootedTree(T value) { + public TreeNode(T value) { this.value = value; } - private RootedTree(RootedTree parent) { + private TreeNode(TreeNode parent) { parent.children.add(this); this.ancestors.add(parent); this.depth = parent.depth + 1; @@ -105,7 +105,7 @@ private RootedTree(RootedTree parent) { } } - public RootedTree setValue(T value) { + public TreeNode setValue(T value) { this.value = value; return this; } @@ -117,8 +117,8 @@ public RootedTree setValue(T value) { * * @return added child */ - public RootedTree addChild() { - return new RootedTree(this); + public TreeNode addChild() { + return new TreeNode(this); } /** @@ -129,7 +129,7 @@ public RootedTree addChild() { * @param value value to be stored in new child * @return added child */ - public RootedTree addChild(T value) { + public TreeNode addChild(T value) { return addChild().setValue(value); } @@ -148,14 +148,14 @@ public T getValue() { * @param value value to be find * @return subtree with given value in the root */ - public RootedTree find(T value) { + public TreeNode find(T value) { if (this.value == null) { if (value == null) return this; } else if (this.value.equals(value)) return this; - for (RootedTree child: children) { - final RootedTree res = child.find(value); + for (TreeNode child: children) { + final TreeNode res = child.find(value); if (res != null) return res; } diff --git a/test/com/jwetherell/algorithms/data_structures/test/IntervalSumArrayTest.java b/test/com/jwetherell/algorithms/data_structures/test/IntervalSumTest.java similarity index 83% rename from test/com/jwetherell/algorithms/data_structures/test/IntervalSumArrayTest.java rename to test/com/jwetherell/algorithms/data_structures/test/IntervalSumTest.java index 35770271..2203ef02 100644 --- a/test/com/jwetherell/algorithms/data_structures/test/IntervalSumArrayTest.java +++ b/test/com/jwetherell/algorithms/data_structures/test/IntervalSumTest.java @@ -9,13 +9,13 @@ import org.junit.Test; -import com.jwetherell.algorithms.data_structures.IntervalSumArray; +import com.jwetherell.algorithms.data_structures.IntervalSum; -public class IntervalSumArrayTest { +public class IntervalSumTest { @Test public void properSumAllElementsTest() { - final IntervalSumArray sub = new IntervalSumArray(); + final IntervalSum sub = new IntervalSum(); for (int i = 0; i<=100; i++) sub.add(i); for (int i = 0; i<=100; i++) @@ -29,7 +29,7 @@ public void randomGeneratedTest() { final List list = new ArrayList(); for (int i = 0; i<=100; i++) list.add(i); - final IntervalSumArray sum = new IntervalSumArray(list); + final IntervalSum sum = new IntervalSum(list); for (int i = 0; i<1000000; i++) { final int pos = generator.nextInt(100); final int val = generator.nextInt(2000000) - 1000000; @@ -55,7 +55,7 @@ public void randomGeneratedTest() { @Test public void setIndexOutOfRangeTest() { - final IntervalSumArray sum = new IntervalSumArray(100); + final IntervalSum sum = new IntervalSum(100); boolean thrown = false; try { sum.set(101, 10); @@ -67,7 +67,7 @@ public void setIndexOutOfRangeTest() { @Test public void sumIndexOutOfRangeTest() { - final IntervalSumArray sum = new IntervalSumArray(100); + final IntervalSum sum = new IntervalSum(100); boolean thrown = false; try { sum.sum(101); @@ -79,7 +79,7 @@ public void sumIndexOutOfRangeTest() { @Test public void endBeforeStartTest() { - final IntervalSumArray sum = new IntervalSumArray(100); + final IntervalSum sum = new IntervalSum(100); boolean thrown = false; try { sum.sum(101, 100); diff --git a/test/com/jwetherell/algorithms/data_structures/test/LowestCommonAncestorTest.java b/test/com/jwetherell/algorithms/data_structures/test/LowestCommonAncestorTest.java index b8e43f5f..ae78eabe 100644 --- a/test/com/jwetherell/algorithms/data_structures/test/LowestCommonAncestorTest.java +++ b/test/com/jwetherell/algorithms/data_structures/test/LowestCommonAncestorTest.java @@ -9,23 +9,23 @@ import com.jwetherell.algorithms.data_structures.LowestCommonAncestor; import com.jwetherell.algorithms.data_structures.LowestCommonAncestor.NodesNotInSameTreeException; -import com.jwetherell.algorithms.data_structures.LowestCommonAncestor.RootedTree; +import com.jwetherell.algorithms.data_structures.LowestCommonAncestor.TreeNode; public class LowestCommonAncestorTest { @Test public void largeTreeTest() throws NodesNotInSameTreeException { - final RootedTree root = new RootedTree(); - final RootedTree left = root.addChild(); - final RootedTree middle = root.addChild(); - final RootedTree right = root.addChild(); + final TreeNode root = new TreeNode(); + final TreeNode left = root.addChild(); + final TreeNode middle = root.addChild(); + final TreeNode right = root.addChild(); //long path - RootedTree v = left; + TreeNode v = left; for (int i = 0; i<1000; i++) v = v.addChild(); - RootedTree leftRight = left.addChild(); + TreeNode leftRight = left.addChild(); assertEquals(LowestCommonAncestor.lowestCommonAncestor(v, leftRight), left); for (int i = 0; i<2000; i++) { @@ -37,7 +37,7 @@ public void largeTreeTest() throws NodesNotInSameTreeException { assertEquals(LowestCommonAncestor.lowestCommonAncestor(root, right), root); assertEquals(LowestCommonAncestor.lowestCommonAncestor(root, root), root); - final RootedTree root2 = new RootedTree(); + final TreeNode root2 = new TreeNode(); boolean thrownException = false; try { LowestCommonAncestor.lowestCommonAncestor(v, root2); @@ -46,7 +46,7 @@ public void largeTreeTest() throws NodesNotInSameTreeException { } assertTrue(thrownException); - final RootedTree deepChild = v.addChild(101); + final TreeNode deepChild = v.addChild(101); assertEquals(deepChild, root.find(101)); assertTrue(root.contains(101)); From f067a8955ff2e2fd239e698d03d6c7f66a48392a Mon Sep 17 00:00:00 2001 From: geosmart Date: Wed, 11 Oct 2017 19:16:39 +0800 Subject: [PATCH 56/88] Update BinarySearchTree.java comment rotateRight is not right --- .../jwetherell/algorithms/data_structures/BinarySearchTree.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/jwetherell/algorithms/data_structures/BinarySearchTree.java b/src/com/jwetherell/algorithms/data_structures/BinarySearchTree.java index d2b832a5..f956090c 100644 --- a/src/com/jwetherell/algorithms/data_structures/BinarySearchTree.java +++ b/src/com/jwetherell/algorithms/data_structures/BinarySearchTree.java @@ -185,7 +185,7 @@ protected void rotateLeft(Node node) { * Rotate tree right at sub-tree rooted at node. * * @param node - * Root of tree to rotate left. + * Root of tree to rotate right. */ protected void rotateRight(Node node) { Node parent = node.parent; From c42708bda0dbf68cb0f13e5a74358e4233842f66 Mon Sep 17 00:00:00 2001 From: ParkChangHan Date: Sun, 15 Oct 2017 14:15:02 +0900 Subject: [PATCH 57/88] fix typo --- src/com/jwetherell/algorithms/numbers/Integers.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/jwetherell/algorithms/numbers/Integers.java b/src/com/jwetherell/algorithms/numbers/Integers.java index 809ac8a6..963f585e 100644 --- a/src/com/jwetherell/algorithms/numbers/Integers.java +++ b/src/com/jwetherell/algorithms/numbers/Integers.java @@ -119,7 +119,7 @@ public static final boolean powerOfTwoUsingBits(int numberToCheck) { singleDigits.put(14,"fourteen"); singleDigits.put(15,"fifteen"); singleDigits.put(16,"sixteen"); - singleDigits.put(17,"seventee"); + singleDigits.put(17,"seventeen"); singleDigits.put(18,"eighteen"); singleDigits.put(19,"nineteen"); } From fbf24fa83ba002ff28761f6692f00ae0b5fcdff5 Mon Sep 17 00:00:00 2001 From: ParkChangHan Date: Mon, 13 Nov 2017 13:54:58 +0900 Subject: [PATCH 58/88] Remove obsolete code --- src/com/jwetherell/algorithms/data_structures/List.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/com/jwetherell/algorithms/data_structures/List.java b/src/com/jwetherell/algorithms/data_structures/List.java index 37eb1db8..09d03a8c 100644 --- a/src/com/jwetherell/algorithms/data_structures/List.java +++ b/src/com/jwetherell/algorithms/data_structures/List.java @@ -67,8 +67,8 @@ public boolean remove(T value) { for (int i = 0; i < size; i++) { T obj = array[i]; if (obj.equals(value)) { - if (remove(i)!=null) return true; - return false; + remove(i); + return true; } } return false; From 724ef3c7daa90e8868110041e153c4e77aa5937d Mon Sep 17 00:00:00 2001 From: SungminKim Date: Mon, 20 Nov 2017 15:18:08 +0900 Subject: [PATCH 59/88] Modified Dijkstra test typo --- test/com/jwetherell/algorithms/graph/test/Graphs.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/com/jwetherell/algorithms/graph/test/Graphs.java b/test/com/jwetherell/algorithms/graph/test/Graphs.java index e63e5602..1908497a 100644 --- a/test/com/jwetherell/algorithms/graph/test/Graphs.java +++ b/test/com/jwetherell/algorithms/graph/test/Graphs.java @@ -372,13 +372,13 @@ public void testDijstraUndirected() { for (Graph.Vertex v : map1.keySet()) { final Graph.CostPathPair path1 = map1.get(v); final Graph.CostPathPair path2 = getIdealUndirectedPath(undirected).get(v); - assertTrue("Dijstra's shortest path error. path1="+path1+" path2="+path2, path1.equals(path2)); + assertTrue("Dijkstra's shortest path error. path1="+path1+" path2="+path2, path1.equals(path2)); } final Graph.CostPathPair pair1 = Dijkstra.getShortestPath(undirected.graph, start, end); assertTrue("No path from " + start.getValue() + " to " + end.getValue(), (pair1 != null)); - assertTrue("Dijstra's shortest path error. pair="+pair1+" pair="+getIdealUndirectedPathPair(undirected), pair1.equals(getIdealUndirectedPathPair(undirected))); + assertTrue("Dijkstra's shortest path error. pair="+pair1+" pair="+getIdealUndirectedPathPair(undirected), pair1.equals(getIdealUndirectedPathPair(undirected))); } } From d428afeffd5edc58134b7409dc3acba3fd663237 Mon Sep 17 00:00:00 2001 From: ParkChangHan Date: Mon, 20 Nov 2017 15:21:27 +0900 Subject: [PATCH 60/88] Fixed Param of Comment --- src/com/jwetherell/algorithms/data_structures/BTree.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/jwetherell/algorithms/data_structures/BTree.java b/src/com/jwetherell/algorithms/data_structures/BTree.java index d15d398c..d930076b 100644 --- a/src/com/jwetherell/algorithms/data_structures/BTree.java +++ b/src/com/jwetherell/algorithms/data_structures/BTree.java @@ -109,7 +109,7 @@ public boolean add(T value) { /** * The node's key size is greater than maxKeySize, split down the middle. * - * @param node + * @param nodeToSplit * to split. */ private void split(Node nodeToSplit) { From 6596bbe775a316cbb489837d6c2ebd6ae739f566 Mon Sep 17 00:00:00 2001 From: SungminKim Date: Mon, 20 Nov 2017 15:24:23 +0900 Subject: [PATCH 61/88] Fixed Dijkstra test typo --- test/com/jwetherell/algorithms/graph/test/Graphs.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/com/jwetherell/algorithms/graph/test/Graphs.java b/test/com/jwetherell/algorithms/graph/test/Graphs.java index 1908497a..6a17dcd0 100644 --- a/test/com/jwetherell/algorithms/graph/test/Graphs.java +++ b/test/com/jwetherell/algorithms/graph/test/Graphs.java @@ -361,7 +361,7 @@ private Graph.CostPathPair getIdealDirectedWithNegWeightsPathPair(Direc } @Test - public void testDijstraUndirected() { + public void testDijkstraUndirected() { final UndirectedGraph undirected = new UndirectedGraph(); final Graph.Vertex start = undirected.v1; final Graph.Vertex end = undirected.v5; @@ -546,14 +546,14 @@ public void testDijkstraDirected() { for (Graph.Vertex v : map1.keySet()) { final Graph.CostPathPair path1 = map1.get(v); final Graph.CostPathPair path2 = getIdealDirectedPath(directed).get(v); - assertTrue("Dijstra's shortest path error. path1="+path1+" path2="+path2, path1.equals(path2)); + assertTrue("Dijkstra's shortest path error. path1="+path1+" path2="+path2, path1.equals(path2)); } final Graph.CostPathPair pair1 = Dijkstra.getShortestPath(directed.graph, start, end); assertTrue("No path from "+start.getValue()+" to "+end.getValue(), (pair1!=null)); // Compare pair - assertTrue("Dijstra's shortest path error. pair1="+pair1+" idealPathPair="+getIdealPathPair(directed), pair1.equals(getIdealPathPair(directed))); + assertTrue("Dijkstra's shortest path error. pair1="+pair1+" idealPathPair="+getIdealPathPair(directed), pair1.equals(getIdealPathPair(directed))); } @Test @@ -579,7 +579,7 @@ public void testBellmanFordDirected() { } @Test - public void testDijstraDirectedWihtNegativeWeights() { + public void testDijkstraDirectedWihtNegativeWeights() { final DirectedWithNegativeWeights directedWithNegWeights = new DirectedWithNegativeWeights(); { // DIRECTED GRAPH (WITH NEGATIVE WEIGHTS) final Graph.Vertex start = directedWithNegWeights.v1; From 3126082cae851e3a685fc315947f2af033c89444 Mon Sep 17 00:00:00 2001 From: ParkChangHan Date: Mon, 20 Nov 2017 15:50:11 +0900 Subject: [PATCH 62/88] Fixed param of Comment in getDirenctions --- src/com/jwetherell/algorithms/data_structures/BinaryHeap.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/com/jwetherell/algorithms/data_structures/BinaryHeap.java b/src/com/jwetherell/algorithms/data_structures/BinaryHeap.java index 61f38a16..1b876f36 100644 --- a/src/com/jwetherell/algorithms/data_structures/BinaryHeap.java +++ b/src/com/jwetherell/algorithms/data_structures/BinaryHeap.java @@ -449,8 +449,8 @@ public int size() { /** * Get the navigation directions through the tree to the index. * - * @param index - * of the Node to get directions for. + * @param idx + * index of the Node to get directions for. * @return Integer array representing the directions to the index. */ private static int[] getDirections(int idx) { From 5dc01d3cbe888b9257d34e33daa1c179bec159b6 Mon Sep 17 00:00:00 2001 From: ParkChangHan Date: Mon, 20 Nov 2017 15:50:43 +0900 Subject: [PATCH 63/88] Fixed param of Comment in validateNode --- src/com/jwetherell/algorithms/data_structures/BinaryHeap.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/com/jwetherell/algorithms/data_structures/BinaryHeap.java b/src/com/jwetherell/algorithms/data_structures/BinaryHeap.java index 1b876f36..81932349 100644 --- a/src/com/jwetherell/algorithms/data_structures/BinaryHeap.java +++ b/src/com/jwetherell/algorithms/data_structures/BinaryHeap.java @@ -289,8 +289,8 @@ public boolean validate() { /** * Validate the node for the heap invariants. * - * @param node - * to validate for. + * @param index + * of node to validate for. * @return True if node is valid. */ private boolean validateNode(int index) { From ed54292376c43ca30243407f37604d665de0bd94 Mon Sep 17 00:00:00 2001 From: SungminKim Date: Mon, 20 Nov 2017 16:03:47 +0900 Subject: [PATCH 64/88] Fix incorrected spelling --- src/com/jwetherell/algorithms/numbers/Integers.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/com/jwetherell/algorithms/numbers/Integers.java b/src/com/jwetherell/algorithms/numbers/Integers.java index 963f585e..fb86fd3d 100644 --- a/src/com/jwetherell/algorithms/numbers/Integers.java +++ b/src/com/jwetherell/algorithms/numbers/Integers.java @@ -129,12 +129,12 @@ public static final boolean powerOfTwoUsingBits(int numberToCheck) { multiDigits.put(10,"ten"); multiDigits.put(20,"twenty"); multiDigits.put(30,"thirty"); - multiDigits.put(40,"fourty"); + multiDigits.put(40,"forty"); multiDigits.put(50,"fifty"); multiDigits.put(60,"sixty"); multiDigits.put(70,"seventy"); multiDigits.put(80,"eighty"); - multiDigits.put(90,"ninty"); + multiDigits.put(90,"ninety"); } private static final int BILLION = 1000000000; From c38908c3151c24ea2eacf04dec80ac7e09a90e84 Mon Sep 17 00:00:00 2001 From: SungminKim Date: Mon, 20 Nov 2017 16:04:40 +0900 Subject: [PATCH 65/88] Fix incorrected spelling --- test/com/jwetherell/algorithms/numbers/test/Numbers.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/com/jwetherell/algorithms/numbers/test/Numbers.java b/test/com/jwetherell/algorithms/numbers/test/Numbers.java index dfe714cd..dcf087ab 100644 --- a/test/com/jwetherell/algorithms/numbers/test/Numbers.java +++ b/test/com/jwetherell/algorithms/numbers/test/Numbers.java @@ -91,17 +91,17 @@ public void testToEnglish() { assertTrue("toEnglish error. a="+a+" expected="+check+" got="+english, (check.equals(english))); a = 199; - check = "one-hundred ninty-nine"; + check = "one-hundred ninety-nine"; english = Integers.toEnglish(a); assertTrue("toEnglish error. a="+a+" expected="+check+" got="+english, (check.equals(english))); a = Integer.MAX_VALUE; // 2,147,483,647 - check = "two-billion one-hundred fourty-seven-million four-hundred eighty-three-thousand six-hundred fourty-seven"; + check = "two-billion one-hundred forty-seven-million four-hundred eighty-three-thousand six-hundred forty-seven"; english = Integers.toEnglish(a); assertTrue("toEnglish error. a="+a+" expected="+check+" got="+english, (check.equals(english))); a = Integer.MIN_VALUE+1; // -2,147,483,647 - check = "negative two-billion one-hundred fourty-seven-million four-hundred eighty-three-thousand six-hundred fourty-seven"; + check = "negative two-billion one-hundred forty-seven-million four-hundred eighty-three-thousand six-hundred forty-seven"; english = Integers.toEnglish(a); assertTrue("toEnglish error. a="+a+" expected="+check+" got="+english, (check.equals(english))); } From 616213e71c4b8416764a6f32cda9396c85c2f5b0 Mon Sep 17 00:00:00 2001 From: ParkChangHan Date: Mon, 20 Nov 2017 16:17:53 +0900 Subject: [PATCH 66/88] Test unused Method --- .../data_structures/CompactSuffixTrie.java | 5 +++++ .../test/CompactSuffixTrieTests.java | 22 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/com/jwetherell/algorithms/data_structures/CompactSuffixTrie.java b/src/com/jwetherell/algorithms/data_structures/CompactSuffixTrie.java index bc64b598..b2796543 100644 --- a/src/com/jwetherell/algorithms/data_structures/CompactSuffixTrie.java +++ b/src/com/jwetherell/algorithms/data_structures/CompactSuffixTrie.java @@ -141,4 +141,9 @@ private Set getSuffixes(PatriciaTrie.Node node, String prefix) { public String toString() { return PatriciaTrie.PatriciaTriePrinter.getString(tree); } + + public boolean equals(CompactSuffixTrie trie){ + if(this.getSuffixes().equals(trie.getSuffixes())) return true; + return false; + } } diff --git a/test/com/jwetherell/algorithms/data_structures/test/CompactSuffixTrieTests.java b/test/com/jwetherell/algorithms/data_structures/test/CompactSuffixTrieTests.java index 8b6bce27..f32f3f64 100644 --- a/test/com/jwetherell/algorithms/data_structures/test/CompactSuffixTrieTests.java +++ b/test/com/jwetherell/algorithms/data_structures/test/CompactSuffixTrieTests.java @@ -25,4 +25,26 @@ public void testCompactSuffixTrie() { exists = trie.doesSubStringExist(pass); assertTrue("YIKES!! " + pass + " doesn't exists.", exists); } + + @Test + public void testCompactSuffixTrie_equals() { + String bookkeeper = "bookkeeper"; + CompactSuffixTrie trie = new CompactSuffixTrie(bookkeeper); + + String bookkeeper_1 = "bookkeeper"; + CompactSuffixTrie trie_1 = new CompactSuffixTrie(bookkeeper_1); + + boolean equal = trie.equals(trie_1); + assertTrue("YIKES!! " + bookkeeper + " and " + bookkeeper_1 + " are not equal.", equal); + + + String failed = "failed"; + trie = new CompactSuffixTrie(failed); + + String failed_1 = "failet"; + trie_1 = new CompactSuffixTrie(failed_1); + + equal = trie.equals(trie_1); + assertFalse("YIKES!! " + failed + " and " + failed_1 + " are equal.", equal); + } } From aac1f8b1a704140283e8ca99f762aa5b1d3c95b4 Mon Sep 17 00:00:00 2001 From: ParkChangHan Date: Mon, 27 Nov 2017 16:29:45 +0900 Subject: [PATCH 67/88] Fixed Param comment --- src/com/jwetherell/algorithms/data_structures/HashMap.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/com/jwetherell/algorithms/data_structures/HashMap.java b/src/com/jwetherell/algorithms/data_structures/HashMap.java index 76c669de..6556d4b9 100644 --- a/src/com/jwetherell/algorithms/data_structures/HashMap.java +++ b/src/com/jwetherell/algorithms/data_structures/HashMap.java @@ -212,9 +212,6 @@ private void initializeMap(int length) { * * @param h * hash to get index of. - * @param length - * length of array - * * @return Integer which represents the key. */ private int indexOf(int h) { From ac23dab6c7d6663808d28e2fc920d43cbe02da5d Mon Sep 17 00:00:00 2001 From: ParkChangHan Date: Mon, 27 Nov 2017 16:34:11 +0900 Subject: [PATCH 68/88] Fixed Param comment in InterverTree --- .../algorithms/data_structures/IntervalTree.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/com/jwetherell/algorithms/data_structures/IntervalTree.java b/src/com/jwetherell/algorithms/data_structures/IntervalTree.java index a04113ba..1a82ef30 100644 --- a/src/com/jwetherell/algorithms/data_structures/IntervalTree.java +++ b/src/com/jwetherell/algorithms/data_structures/IntervalTree.java @@ -314,7 +314,7 @@ public IntervalData(long start, long end, O object) { /** * Interval data list which should all be unique * - * @param list + * @param set * of interval data objects */ public IntervalData(long start, long end, Set set) { @@ -389,10 +389,9 @@ public IntervalData copy() { /** * Query inside this data object. * - * @param start - * of range to query for. - * @param end - * of range to query for. + * @param index + * to find Data. + * * @return Data queried for or NULL if it doesn't match the query. */ public IntervalData query(long index) { From b85ef7e0cb69af9ce2e8673594a6c087ac895929 Mon Sep 17 00:00:00 2001 From: ParkChangHan Date: Mon, 27 Nov 2017 16:38:43 +0900 Subject: [PATCH 69/88] Fixed Param comment in SegmentTree --- src/com/jwetherell/algorithms/data_structures/SegmentTree.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/jwetherell/algorithms/data_structures/SegmentTree.java b/src/com/jwetherell/algorithms/data_structures/SegmentTree.java index 9a04b8e6..fb516d8e 100644 --- a/src/com/jwetherell/algorithms/data_structures/SegmentTree.java +++ b/src/com/jwetherell/algorithms/data_structures/SegmentTree.java @@ -696,7 +696,7 @@ public IntervalData(long start, long end, O object) { /** * Interval data list which should all be unique * - * @param list + * @param set * of interval data objects */ public IntervalData(long start, long end, Set set) { From 5033342d1c679beb35ece62592b80cb4c66df59a Mon Sep 17 00:00:00 2001 From: ParkChangHan Date: Mon, 27 Nov 2017 16:45:53 +0900 Subject: [PATCH 70/88] Fixed Param comment in ConnectedComponents --- src/com/jwetherell/algorithms/graph/ConnectedComponents.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/com/jwetherell/algorithms/graph/ConnectedComponents.java b/src/com/jwetherell/algorithms/graph/ConnectedComponents.java index dae44174..e096950c 100644 --- a/src/com/jwetherell/algorithms/graph/ConnectedComponents.java +++ b/src/com/jwetherell/algorithms/graph/ConnectedComponents.java @@ -25,7 +25,8 @@ private ConnectedComponents() { } /** * Finds the connected components subsets of the Graph. * - * @param g Graph to find connected components. + * @param graph + * to find connected components. * @return List of connected components in the Graph. */ public static final > List>> getConnectedComponents(Graph graph) { From 2b0a3b03a8d13ac06532c3a803ec08286eaa8bb6 Mon Sep 17 00:00:00 2001 From: aniders <33834501+aniders@users.noreply.github.com> Date: Wed, 14 Feb 2018 23:45:39 +0530 Subject: [PATCH 71/88] Update Knapsack.java Changed OR condition to &&, OR may possibly result in ArrayIndexOutOfBoundException , (as it does for following input capacity : 60, weights: [10, 20, 33], values: [10, 3, 30]) --- src/com/jwetherell/algorithms/mathematics/Knapsack.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/jwetherell/algorithms/mathematics/Knapsack.java b/src/com/jwetherell/algorithms/mathematics/Knapsack.java index 69f848c2..09079ce9 100644 --- a/src/com/jwetherell/algorithms/mathematics/Knapsack.java +++ b/src/com/jwetherell/algorithms/mathematics/Knapsack.java @@ -40,7 +40,7 @@ public static final int[] zeroOneKnapsack(int[] values, int[] weights, int capac final List list = new ArrayList(); int i = height - 1; int j = width - 1; - while (i != 0 || j != 0) { + while (i != 0 && j != 0) { int current = output[i][j]; int above = output[i - 1][j]; if (current == above) { From 7a7549d8dfbd2653839c8f39fc8eaca95f38ee2e Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Thu, 3 May 2018 10:18:30 -0400 Subject: [PATCH 72/88] Closes #91 Bug fix --- .../LongestIncreasingSubsequence.java | 50 +++++++++++++------ .../algorithms/sequence/test/Sequences.java | 2 +- 2 files changed, 36 insertions(+), 16 deletions(-) diff --git a/src/com/jwetherell/algorithms/sequence/LongestIncreasingSubsequence.java b/src/com/jwetherell/algorithms/sequence/LongestIncreasingSubsequence.java index 4421896b..598f6885 100644 --- a/src/com/jwetherell/algorithms/sequence/LongestIncreasingSubsequence.java +++ b/src/com/jwetherell/algorithms/sequence/LongestIncreasingSubsequence.java @@ -1,9 +1,5 @@ package com.jwetherell.algorithms.sequence; -import com.jwetherell.algorithms.search.LowerBound; - -import java.util.Arrays; - /** * In computer science, the longest increasing subsequence problem is to find a subsequence of a given sequence in which the subsequence's elements are in sorted order, lowest to highest, and in * which the subsequence is as long as possible. This subsequence is not necessarily contiguous, or unique. @@ -20,19 +16,43 @@ private LongestIncreasingSubsequence() { } /** * Longest increasing subsequence solved using dynamic programming. */ - public static int[] getLongestIncreasingSubsequence(int[] sequence) { - final int[] resultSequence = new int[sequence.length]; + public static int[] getLongestIncreasingSubsequence(int[] X) { + final int[] P = new int[X.length]; + final int[] M = new int[X.length+1]; + int L = 0; + for (int i=0; i L) { + // If we found a subsequence longer than any we've found yet, update L + L = newL; + } + } - int resultLength = 0; - for (int i = 0; i < sequence.length; ++i) { - // try to find the best place for new element in sorted result - final int pos = LowerBound.lowerBound(resultSequence, resultLength, sequence[i]); //O(log n) - // if the best place is at the end increase result length - if (pos >= resultLength) - resultLength++; - resultSequence[pos] = sequence[i]; + // Reconstruct the longest increasing subsequence + final int[] S = new int[L]; + int k = M[L]; + for (int i=L-1; i>=0; i--) { + S[i] = X[k]; + k = P[k]; } - return Arrays.copyOfRange(resultSequence, 0, resultLength); + return S; } } diff --git a/test/com/jwetherell/algorithms/sequence/test/Sequences.java b/test/com/jwetherell/algorithms/sequence/test/Sequences.java index 18b7d0c1..bd3fa1d8 100644 --- a/test/com/jwetherell/algorithms/sequence/test/Sequences.java +++ b/test/com/jwetherell/algorithms/sequence/test/Sequences.java @@ -141,7 +141,7 @@ public void testLongestIncreasingSubsequence() { sequencesLis.add(new int[]{1, 2, 3}); sequences.add(new int[]{0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15}); - sequencesLis.add(new int[]{0, 1, 3, 7, 11, 15}); + sequencesLis.add(new int[]{0, 2, 6, 9, 11, 15}); assertTrue("Longest increasing subsequence error. Sequences size=" + sequences.size() + " SequencesList size:" + sequencesLis.size(), sequences.size() == sequencesLis.size()); From 4c8e4c42f04f1d8b827dd7196e6e0f28a5091960 Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Thu, 21 Feb 2019 09:21:34 -0500 Subject: [PATCH 73/88] Updates to yaml to get jdk6 working in travis-ci --- .travis.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e2324a51..3c8d4d3f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,15 @@ addons: - openjdk-6-jdk language: java +dist: trusty + +# for gh-1388 (workaround for supporting test using OpenJDK 6) +matrix: + include: + - env: JDK='OpenJDK 6' + before_install: + - echo "MAVEN_OPTS='-Dlicense.skip=true'" > ~/.mavenrc + - TRAVIS_JDK_VERSION=openjdk6 jdk: - oraclejdk9 @@ -22,7 +31,7 @@ jdk: # - openjdk9 - openjdk8 - openjdk7 - - openjdk6 +# - openjdk6 env: - TEST_SUITE=run_tests From 62e9f1dceb95faae646826377e569dbf7ba9f25d Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Thu, 21 Feb 2019 09:31:26 -0500 Subject: [PATCH 74/88] Updates to yaml to get jdk6 working in travis-ci --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3c8d4d3f..f34c197c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,7 +17,9 @@ dist: trusty # for gh-1388 (workaround for supporting test using OpenJDK 6) matrix: include: - - env: JDK='OpenJDK 6' + env: + - JDK='OpenJDK 6' + - TEST_SUITE=run_tests before_install: - echo "MAVEN_OPTS='-Dlicense.skip=true'" > ~/.mavenrc - TRAVIS_JDK_VERSION=openjdk6 From f0639aa08edeca4781714538d027eeb51d8e4735 Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Thu, 21 Feb 2019 09:50:48 -0500 Subject: [PATCH 75/88] Dropping builds for jdk6 because travis-ci no longer supports --- .travis.yml | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/.travis.yml b/.travis.yml index f34c197c..40a330e3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,23 +6,7 @@ before_script: - echo $JAVA_OPTS - echo $ANT_OPTS -addons: - apt: - packages: - - openjdk-6-jdk - language: java -dist: trusty - -# for gh-1388 (workaround for supporting test using OpenJDK 6) -matrix: - include: - env: - - JDK='OpenJDK 6' - - TEST_SUITE=run_tests - before_install: - - echo "MAVEN_OPTS='-Dlicense.skip=true'" > ~/.mavenrc - - TRAVIS_JDK_VERSION=openjdk6 jdk: - oraclejdk9 From e5966440895ebed5d9a448ad9785db090b99c2e5 Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Thu, 21 Feb 2019 10:26:09 -0500 Subject: [PATCH 76/88] Fixed the Queue grow method comment about resizing --- src/com/jwetherell/algorithms/data_structures/Queue.java | 2 +- .../jwetherell/algorithms/data_structures/test/QueueTests.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/com/jwetherell/algorithms/data_structures/Queue.java b/src/com/jwetherell/algorithms/data_structures/Queue.java index 1a078f71..845e65e5 100644 --- a/src/com/jwetherell/algorithms/data_structures/Queue.java +++ b/src/com/jwetherell/algorithms/data_structures/Queue.java @@ -111,7 +111,7 @@ private boolean remove(int index) { return true; } - // Grow the array by 50% and rearrange to make sequential + // Triple the size of the underlying array and rearrange to make sequential private void grow(int size) { int growSize = (size + (size<<1)); T[] temp = (T[]) new Object[growSize]; diff --git a/test/com/jwetherell/algorithms/data_structures/test/QueueTests.java b/test/com/jwetherell/algorithms/data_structures/test/QueueTests.java index b4512e57..153efc46 100644 --- a/test/com/jwetherell/algorithms/data_structures/test/QueueTests.java +++ b/test/com/jwetherell/algorithms/data_structures/test/QueueTests.java @@ -16,7 +16,7 @@ public class QueueTests { @Test public void testArrayQueue() { - TestData data = Utils.generateTestData(100); + TestData data = Utils.generateTestData(100000); String aName = "Queue [array]"; Queue.ArrayQueue aQueue = new Queue.ArrayQueue(); From cdafbb9471fd2876b0df7657be4d18a43d8a7110 Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Thu, 21 Feb 2019 11:17:36 -0500 Subject: [PATCH 77/88] Found a bug in the grow method of the ArrayQueue --- .../jwetherell/algorithms/data_structures/Queue.java | 10 +++++----- .../algorithms/data_structures/test/QueueTests.java | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/com/jwetherell/algorithms/data_structures/Queue.java b/src/com/jwetherell/algorithms/data_structures/Queue.java index 845e65e5..4aa200b7 100644 --- a/src/com/jwetherell/algorithms/data_structures/Queue.java +++ b/src/com/jwetherell/algorithms/data_structures/Queue.java @@ -117,11 +117,11 @@ private void grow(int size) { T[] temp = (T[]) new Object[growSize]; // Since the array can wrap around, make sure you grab the first chunk int adjLast = lastIndex % array.length; - if (adjLast < firstIndex) { - System.arraycopy(array, 0, temp, array.length-adjLast, adjLast+1); + if (adjLast > 0 && adjLast <= firstIndex) { + System.arraycopy(array, 0, temp, array.length-adjLast, adjLast); } // Copy the remaining - System.arraycopy(array, firstIndex, temp, 0, array.length-firstIndex); + System.arraycopy(array, firstIndex, temp, 0, array.length - firstIndex); array = null; array = temp; lastIndex = (lastIndex - firstIndex); @@ -134,9 +134,9 @@ private void shrink() { T[] temp = (T[]) new Object[shrinkSize]; // Since the array can wrap around, make sure you grab the first chunk int adjLast = lastIndex % array.length; - int endIndex = (lastIndex>array.length)?array.length:lastIndex; + int endIndex = (lastIndex>array.length) ? array.length : lastIndex; if (adjLast <= firstIndex) { - System.arraycopy(array, 0, temp, array.length-firstIndex, adjLast); + System.arraycopy(array, 0, temp, array.length - firstIndex, adjLast); } // Copy the remaining System.arraycopy(array, firstIndex, temp, 0, endIndex-firstIndex); diff --git a/test/com/jwetherell/algorithms/data_structures/test/QueueTests.java b/test/com/jwetherell/algorithms/data_structures/test/QueueTests.java index 153efc46..9dfb6759 100644 --- a/test/com/jwetherell/algorithms/data_structures/test/QueueTests.java +++ b/test/com/jwetherell/algorithms/data_structures/test/QueueTests.java @@ -16,7 +16,7 @@ public class QueueTests { @Test public void testArrayQueue() { - TestData data = Utils.generateTestData(100000); + TestData data = Utils.generateTestData(2500); String aName = "Queue [array]"; Queue.ArrayQueue aQueue = new Queue.ArrayQueue(); @@ -30,7 +30,7 @@ public void testArrayQueue() { @Test public void testLinkedQueue() { - TestData data = Utils.generateTestData(100); + TestData data = Utils.generateTestData(250); String lName = "Queue [linked]"; Queue.LinkedQueue lQueue = new Queue.LinkedQueue(); From b98248222b875c56c8caf69eec44574ee05dd1ce Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Thu, 21 Feb 2019 11:29:19 -0500 Subject: [PATCH 78/88] Fixed a bug in the getHeadValue of the Heap structures --- .../data_structures/BinaryHeap.java | 2 +- .../data_structures/test/BinaryHeapTests.java | 30 +++++++++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/com/jwetherell/algorithms/data_structures/BinaryHeap.java b/src/com/jwetherell/algorithms/data_structures/BinaryHeap.java index 81932349..ac2ae1f9 100644 --- a/src/com/jwetherell/algorithms/data_structures/BinaryHeap.java +++ b/src/com/jwetherell/algorithms/data_structures/BinaryHeap.java @@ -341,7 +341,7 @@ public T[] getHeap() { */ @Override public T getHeadValue() { - if (array.length == 0) return null; + if (size == 0 || array.length == 0) return null; return array[0]; } diff --git a/test/com/jwetherell/algorithms/data_structures/test/BinaryHeapTests.java b/test/com/jwetherell/algorithms/data_structures/test/BinaryHeapTests.java index 865c266b..68591215 100644 --- a/test/com/jwetherell/algorithms/data_structures/test/BinaryHeapTests.java +++ b/test/com/jwetherell/algorithms/data_structures/test/BinaryHeapTests.java @@ -1,6 +1,7 @@ package com.jwetherell.algorithms.data_structures.test; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertNull; import java.util.Collection; @@ -16,7 +17,7 @@ public class BinaryHeapTests { @Test public void testMinHeap() { - TestData data = Utils.generateTestData(100); + TestData data = Utils.generateTestData(2500); String aNameMin = "Min-Heap [array]"; BinaryHeap.BinaryHeapArray aHeapMin = new BinaryHeap.BinaryHeapArray(BinaryHeap.Type.MIN); @@ -26,6 +27,12 @@ public void testMinHeap() { assertTrue(JavaCollectionTest.testCollection(aCollectionMin, Integer.class, aNameMin, data.unsorted, data.sorted, data.invalid)); + BinaryHeap.BinaryHeapArray aHeapNull = new BinaryHeap.BinaryHeapArray(BinaryHeap.Type.MIN); + aHeapNull.add(10); + aHeapNull.add(11); + aHeapNull.clear(); + assertNull(aHeapNull.getHeadValue()); // we expect null here + String tNameMin = "Min-Heap [tree]"; BinaryHeap.BinaryHeapTree tHeapMin = new BinaryHeap.BinaryHeapTree(BinaryHeap.Type.MIN); Collection tCollectionMin = tHeapMin.toCollection(); @@ -33,11 +40,18 @@ public void testMinHeap() { data.unsorted, data.sorted, data.invalid)); assertTrue(JavaCollectionTest.testCollection(tCollectionMin, Integer.class, tNameMin, data.unsorted, data.sorted, data.invalid)); + + BinaryHeap.BinaryHeapTree tHeapNull = new BinaryHeap.BinaryHeapTree(BinaryHeap.Type.MIN); + tHeapNull.add(10); + tHeapNull.add(11); + tHeapNull.clear(); + assertNull(tHeapNull.getHeadValue()); // we expect null here + } @Test public void testMaxHeap() { - TestData data = Utils.generateTestData(1000); + TestData data = Utils.generateTestData(2500); String aNameMax = "Max-Heap [array]"; BinaryHeap.BinaryHeapArray aHeapMax = new BinaryHeap.BinaryHeapArray(BinaryHeap.Type.MAX); @@ -47,6 +61,12 @@ public void testMaxHeap() { assertTrue(JavaCollectionTest.testCollection(aCollectionMax, Integer.class, aNameMax, data.unsorted, data.sorted, data.invalid)); + BinaryHeap.BinaryHeapArray aHeapNull = new BinaryHeap.BinaryHeapArray(BinaryHeap.Type.MAX); + aHeapNull.add(10); + aHeapNull.add(11); + aHeapNull.clear(); + assertNull(aHeapNull.getHeadValue()); // we expect null here + String lNameMax = "Max-Heap [tree]"; BinaryHeap.BinaryHeapTree tHeapMax = new BinaryHeap.BinaryHeapTree(BinaryHeap.Type.MAX); Collection tCollectionMax = tHeapMax.toCollection(); @@ -54,5 +74,11 @@ public void testMaxHeap() { data.unsorted, data.sorted, data.invalid)); assertTrue(JavaCollectionTest.testCollection(tCollectionMax, Integer.class, lNameMax, data.unsorted, data.sorted, data.invalid)); + + BinaryHeap.BinaryHeapTree tHeapNull = new BinaryHeap.BinaryHeapTree(BinaryHeap.Type.MAX); + tHeapNull.add(10); + tHeapNull.add(11); + tHeapNull.clear(); + assertNull(tHeapNull.getHeadValue()); // we expect null here } } From edf84c527578997bc5e409f4166dd68c17d05790 Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Thu, 21 Feb 2019 12:11:39 -0500 Subject: [PATCH 79/88] Fixed a bug in the ArrayQueue iterator --- .../algorithms/data_structures/Queue.java | 2 +- .../data_structures/test/QueueTests.java | 22 +++++++++++++++++++ .../test/common/JavaCollectionTest.java | 6 +++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/com/jwetherell/algorithms/data_structures/Queue.java b/src/com/jwetherell/algorithms/data_structures/Queue.java index 4aa200b7..92962a4d 100644 --- a/src/com/jwetherell/algorithms/data_structures/Queue.java +++ b/src/com/jwetherell/algorithms/data_structures/Queue.java @@ -563,7 +563,7 @@ public boolean hasNext() { public T next() { if (queue.firstIndex+index < queue.lastIndex) { last = queue.firstIndex+index; - return queue.array[queue.firstIndex+index++]; + return queue.array[(queue.firstIndex + index++) % queue.array.length]; } return null; } diff --git a/test/com/jwetherell/algorithms/data_structures/test/QueueTests.java b/test/com/jwetherell/algorithms/data_structures/test/QueueTests.java index 9dfb6759..6f2be148 100644 --- a/test/com/jwetherell/algorithms/data_structures/test/QueueTests.java +++ b/test/com/jwetherell/algorithms/data_structures/test/QueueTests.java @@ -3,6 +3,7 @@ import static org.junit.Assert.assertTrue; import java.util.Collection; +import java.util.Iterator; import org.junit.Test; @@ -26,6 +27,17 @@ public void testArrayQueue() { data.unsorted, data.invalid)); assertTrue(JavaCollectionTest.testCollection(aCollection, Integer.class, aName, data.unsorted, data.sorted, data.invalid)); + + // Specific test based on bug + aQueue = new Queue.ArrayQueue(); + for (int i = 0; i < 1024; i++) { + aQueue.offer(i); + } + aQueue.poll(); + aQueue.offer(1024); + Iterator it = aQueue.toQueue().iterator(); + while (it.hasNext()) + it.next(); } @Test @@ -40,5 +52,15 @@ public void testLinkedQueue() { data.unsorted, data.invalid)); assertTrue(JavaCollectionTest.testCollection(lCollection, Integer.class, lName, data.unsorted, data.sorted, data.invalid)); + + lQueue = new Queue.LinkedQueue(); + for (int i = 0; i < 1024; i++) { + lQueue.offer(i); + } + lQueue.poll(); + lQueue.offer(1024); + Iterator it = lQueue.toQueue().iterator(); + while (it.hasNext()) + it.next(); } } diff --git a/test/com/jwetherell/algorithms/data_structures/test/common/JavaCollectionTest.java b/test/com/jwetherell/algorithms/data_structures/test/common/JavaCollectionTest.java index 12e790a7..c4338d5a 100644 --- a/test/com/jwetherell/algorithms/data_structures/test/common/JavaCollectionTest.java +++ b/test/com/jwetherell/algorithms/data_structures/test/common/JavaCollectionTest.java @@ -78,6 +78,12 @@ private static > boolean addAndRemoveInOrder(Collection< return false; } + if (!IteratorTest.testIterator(collection.iterator())) { + System.err.println(name+" addAndRemoveInOrder iterator failed."); + Utils.handleError(data,collection); + return false; + } + for (int i = 0; i < data.length; i++) { Integer value = data[i]; T item = Utils.parseT(value, type); From 356dfb1daff89b983194c192c7534fa3b3a30126 Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Thu, 21 Feb 2019 12:16:28 -0500 Subject: [PATCH 80/88] Fixed a bug in the getHeadValue of the Heap structures --- src/com/jwetherell/algorithms/data_structures/BinaryHeap.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/jwetherell/algorithms/data_structures/BinaryHeap.java b/src/com/jwetherell/algorithms/data_structures/BinaryHeap.java index ac2ae1f9..08855e28 100644 --- a/src/com/jwetherell/algorithms/data_structures/BinaryHeap.java +++ b/src/com/jwetherell/algorithms/data_structures/BinaryHeap.java @@ -372,7 +372,7 @@ public String toString() { protected static class HeapPrinter { public static > String getString(BinaryHeapArray tree) { - if (tree.array.length == 0) + if (tree.size == 0 || tree.array.length == 0) return "Tree has no nodes."; T root = tree.array[0]; From d3d1d03f029f2188b98579f7278b7e1221ad47db Mon Sep 17 00:00:00 2001 From: Nishant Ingle Date: Sat, 26 Oct 2019 17:06:15 +0530 Subject: [PATCH 81/88] Added Comment on Linear Search Logic --- src/com/jwetherell/algorithms/search/BinarySearch.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/com/jwetherell/algorithms/search/BinarySearch.java b/src/com/jwetherell/algorithms/search/BinarySearch.java index 8d3f8521..b0cbe03d 100644 --- a/src/com/jwetherell/algorithms/search/BinarySearch.java +++ b/src/com/jwetherell/algorithms/search/BinarySearch.java @@ -56,6 +56,7 @@ private static int recursiveFind(int value, int start, int end, boolean optimize } private static final int linearSearch(int value, int start, int end) { + // From index i = start to i = end check if value matches sorted[i] for (int i = start; i <= end; i++) { int iValue = sorted[i]; if (value == iValue) From 16f2fc18ff5ac71ae3eed21dcc4cb8aa7e6711c5 Mon Sep 17 00:00:00 2001 From: gauravdarbhanga <57192490+gauravdarbhanga@users.noreply.github.com> Date: Wed, 30 Oct 2019 23:48:53 +0530 Subject: [PATCH 82/88] Update BubbleSort.java adding comments on the method. --- src/com/jwetherell/algorithms/sorts/BubbleSort.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/com/jwetherell/algorithms/sorts/BubbleSort.java b/src/com/jwetherell/algorithms/sorts/BubbleSort.java index 3ac320ff..824e4e17 100644 --- a/src/com/jwetherell/algorithms/sorts/BubbleSort.java +++ b/src/com/jwetherell/algorithms/sorts/BubbleSort.java @@ -21,7 +21,8 @@ public class BubbleSort> { private BubbleSort() { } - + //@param unsorted array + //@return sorted array public static > T[] sort(T[] unsorted) { boolean swapped = true; int length = unsorted.length; @@ -37,7 +38,7 @@ public static > T[] sort(T[] unsorted) { } return unsorted; } - + //swapping the value private static > void swap(int index1, int index2, T[] unsorted) { T value = unsorted[index1]; unsorted[index1] = unsorted[index2]; From 38d06ee316907262b20ba695f99c129e14eadef4 Mon Sep 17 00:00:00 2001 From: gauravdarbhanga <57192490+gauravdarbhanga@users.noreply.github.com> Date: Wed, 30 Oct 2019 23:59:12 +0530 Subject: [PATCH 83/88] Update CountingSort.java Did comment on the method. --- src/com/jwetherell/algorithms/sorts/CountingSort.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/com/jwetherell/algorithms/sorts/CountingSort.java b/src/com/jwetherell/algorithms/sorts/CountingSort.java index f1593c50..31e6a289 100644 --- a/src/com/jwetherell/algorithms/sorts/CountingSort.java +++ b/src/com/jwetherell/algorithms/sorts/CountingSort.java @@ -27,26 +27,26 @@ private CountingSort() { } public static Integer[] sort(Integer[] unsorted) { int maxValue = findMax(unsorted); - int[] counts = new int[maxValue + 1]; + int[] counts = new int[maxValue + 1];//counts number of elements updateCounts(unsorted, counts); populateCounts(unsorted, counts); return unsorted; } - + //finding maximum value in unsorted array private static int findMax(Integer[] unsorted) { - int max = Integer.MIN_VALUE; + int max = Integer.MIN_VALUE;//assume minimum value(-2147483648) of interger is maximum for (int i : unsorted) { if (i > max) max = i; } return max; } - + //Incrementing the number of counts in unsorted array private static void updateCounts(Integer[] unsorted, int[] counts) { for (int e : unsorted) counts[e]++; } - + private static void populateCounts(Integer[] unsorted, int[] counts) { int index = 0; for (int i = 0; i < counts.length; i++) { From 71d8b30bba0f426607412927279b53637f8b958b Mon Sep 17 00:00:00 2001 From: gauravdarbhanga <57192490+gauravdarbhanga@users.noreply.github.com> Date: Thu, 31 Oct 2019 00:06:22 +0530 Subject: [PATCH 84/88] Update BinarySearch.java --- src/com/jwetherell/algorithms/search/BinarySearch.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/com/jwetherell/algorithms/search/BinarySearch.java b/src/com/jwetherell/algorithms/search/BinarySearch.java index 8d3f8521..42af2c2f 100644 --- a/src/com/jwetherell/algorithms/search/BinarySearch.java +++ b/src/com/jwetherell/algorithms/search/BinarySearch.java @@ -29,7 +29,8 @@ public static final int find(int value, int[] array, boolean optimize) { BinarySearch.sorted = null; } } - + //Recursively find the element + //@return find the element value by recursively private static int recursiveFind(int value, int start, int end, boolean optimize) { if (start == end) { int lastValue = sorted[start]; // start==end @@ -43,8 +44,10 @@ private static int recursiveFind(int value, int start, int end, boolean optimize final int middle = low + ((high - low) / 2); final int middleValue = sorted[middle]; + //checks if the middle index is element if (value == middleValue) return middle; + //if value is greater than move to right if (value > middleValue) { if (optimize && (end - middle) <= SWITCH_TO_BRUTE_FORCE) return linearSearch(value, middle + 1, end); @@ -54,7 +57,10 @@ private static int recursiveFind(int value, int start, int end, boolean optimize return linearSearch(value, start, middle - 1); return recursiveFind(value, start, middle - 1, optimize); } - + //Linear search to find the element. + //@value the element we want to find. + //@start first index of the array in the array + //@end last index of the array in the array. private static final int linearSearch(int value, int start, int end) { for (int i = start; i <= end; i++) { int iValue = sorted[i]; From 4e8de437ac1e921b319a8ff876e2ff81f1d9c7de Mon Sep 17 00:00:00 2001 From: gauravdarbhanga <57192490+gauravdarbhanga@users.noreply.github.com> Date: Thu, 31 Oct 2019 00:14:19 +0530 Subject: [PATCH 85/88] Update LowerBound.java --- src/com/jwetherell/algorithms/search/LowerBound.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/com/jwetherell/algorithms/search/LowerBound.java b/src/com/jwetherell/algorithms/search/LowerBound.java index 569e4532..9e6cd353 100644 --- a/src/com/jwetherell/algorithms/search/LowerBound.java +++ b/src/com/jwetherell/algorithms/search/LowerBound.java @@ -23,6 +23,7 @@ public static int lowerBound(int[] array, int length, int value) { int high = length; while (low < high) { final int mid = (low + high) / 2; + //checks if the value is less than middle element of the array if (value <= array[mid]) { high = mid; } else { From 769cb67c4364301a91ec82b7381ddb9f12b1a34e Mon Sep 17 00:00:00 2001 From: BryanChan777 <43082778+BryanChan777@users.noreply.github.com> Date: Sat, 23 Nov 2019 17:16:39 -0800 Subject: [PATCH 86/88] Removed hedging and improved grammar in README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 459c4d35..0101b605 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ Java : Algorithms and Data Structure ![alt tag](https://api.travis-ci.org/phishman3579/java-algorithms-implementation.svg?branch=master) ============================== -Algorithms and Data Structures implemented in Java +The algorithms and data structures are implemented in Java. -This is a collection of algorithms and data structures which I've implement over the years in my academic and professional life. The code isn't overly-optimized but is written to be correct and readable. The algorithms and data structures are well tested and, unless noted, are believe to be 100% correct. +This is a collection of algorithms and data structures I've implemented in my academic and professional life. The code isn't optimized but is written to be correct and readable. The algorithms and data structures are tested and, unless noted, believed to be correct. ## Created by Justin Wetherell From 81a028f7404765d5b80b882186cac7d1e3af0205 Mon Sep 17 00:00:00 2001 From: KisaragiEffective <48310258+KisaragiEffective@users.noreply.github.com> Date: Fri, 3 Jan 2020 01:50:13 +0900 Subject: [PATCH 87/88] Update README.md close #105 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 459c4d35..d2a96aaa 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ This is a collection of algorithms and data structures which I've implement over * [Hash Map (associative array)](src/com/jwetherell/algorithms/data_structures/HashMap.java) * [Interval Tree](src/com/jwetherell/algorithms/data_structures/IntervalTree.java) * [Implicit Key Treap](src/com/jwetherell/algorithms/data_structures/ImplicitKeyTreap.java) -* [KD Tree (k-dimensional tree or k-d tree)](src/com/jwetherell/algorithms/data_structures/KDTree.java) +* [KD Tree (k-dimensional tree or k-d tree)](src/com/jwetherell/algorithms/data_structures/KdTree.java) * [List [backed by an array or a linked list]](src/com/jwetherell/algorithms/data_structures/List.java) * [LCP Array (Longest Common Prefix) [backed by a Suffix Array]](src/com/jwetherell/algorithms/data_structures/LCPArray.java) * [Matrix](src/com/jwetherell/algorithms/data_structures/Matrix.java) From 6328fcf45f769b79c34089a4cf4ba50f909fa594 Mon Sep 17 00:00:00 2001 From: Justin Wetherell Date: Wed, 29 Jan 2020 08:17:54 -0500 Subject: [PATCH 88/88] Update .travis.yml --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 40a330e3..3a3703f6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,8 @@ before_script: - echo $JAVA_OPTS - echo $ANT_OPTS +dist: trusty + language: java jdk: