From f35e26b3ab8f6c65cab5493d14194ae07042b2d3 Mon Sep 17 00:00:00 2001 From: Lorenzo Rossi Date: Thu, 18 Oct 2018 22:59:24 +0200 Subject: [PATCH] fenwick_tree.java: Add Fenwick Tree Data This adds Fenwick Data Structure which can update an element of a list and query the sum of any range of it in only O(log(N)) time complexity. Closes https://github.com/NITSkmOS/Algorithms/issues/218 --- README.md | 1 + fenwick_tree/java/fenwick_tree.java | 100 ++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 fenwick_tree/java/fenwick_tree.java diff --git a/README.md b/README.md index d3b51b1d..08780a08 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ This repository contains examples of various algorithms written on different pro | [Linear Linked List](https://en.wikipedia.org/wiki/Linked_list) | [:octocat:](linked_list/C) | [:octocat:](linked_list/Cpp) | | [:octocat:](linked_list/Python) | | [AVL Tree](https://en.wikipedia.org/wiki/AVL_tree) | [:octocat:](avl_tree/C) | | [:octocat:](avl_tree/Java) | [:octocat:](avl_tree/Python) | | [Binary Search Tree](https://en.wikipedia.org/wiki/Binary_search_tree) | | [:octocat:](binary_search_tree/Cpp) | | | +| [Fenwick Tree](https://en.wikipedia.org/wiki/Fenwick_tree) | | | [:octocat:](fenwick_tree/java) | | ## Sample Run diff --git a/fenwick_tree/java/fenwick_tree.java b/fenwick_tree/java/fenwick_tree.java new file mode 100644 index 00000000..b3d739b4 --- /dev/null +++ b/fenwick_tree/java/fenwick_tree.java @@ -0,0 +1,100 @@ +public class fenwick_tree { + private int[] data; + + public fenwick_tree(int size) { + data = new int[size + 1]; + } + + /** + * Returns the sum from 0 to right (inclusive) + * @param right the inclusive right index + * @return sum([0; right]) + */ + public int sum(int right) { + int sum = 0; + int index = right + 1;// Convert to 1-based index + for (; index > 0; index -= LSB(index)) { + sum += data[index]; + } + return sum; + } + + /** + * Returns the sum from left (inclusive) to right (inclusive) + * @param left the inclusive left index + * @param right the inclusive right index + * @return sum([left; right]) + */ + public int sum(int left, int right) { + return sum(right) - sum(left - 1); + } + + /** + * Add the difference to the data index + * @param index the index to update + * @param diff the amount to add to that index + */ + public void add(int index, int diff) { + index++; // Convert to 1-based index + for (; index < data.length; index += LSB(index)) { + data[index] += diff; + } + } + + /** + * Returns the tree's capacity + * @return tree sizes + */ + public int getSize() { + return data.length - 1;// The 0 index isn't used + } + + private static int LSB(int x) { + // Last Significant Bit + return x & -x; + } + + + /** + * Example usage + * run with "java -ea fenwick_tree" to enable assertions + */ + public static void main(String[] args) { + fenwick_tree tree = new fenwick_tree(8); + + // Set initial value (by default it's 0) + for (int i = 0; i < 8; i++) { + tree.add(i, i); + } + // Now it's 0, 1, 2, 3, 4, 5, 6, 7 + + // [0, 1, 2, 3, 4, 5, 6, 7] + // ^--------------------^ + // 0 + 1 + 2 ... + 7 = 28 + assert tree.sum(0, 7) == 28; + + // [0, 1, 2, 3, 4, 5, 6, 7] + // ^-----^ + // 4 + 5 + 6 = 15 + assert tree.sum(4, 6) == 15; + + // [0, 1, 2, 3, 4, 5, 6, 7] + // ^--------^ + // 0 + 1 + 2 + 3 = 6 + assert tree.sum(3) == 6; + + // Update the numbers again + for (int i = 0; i < 8; i++) { + tree.add(i, 1 - i); + // Initial value i + // Added: 1 - i + // Res: i + 1 - i = 1 + } + + // [1, 1, 1, 1, 1, 1, 1, 1] + // ^--------------------^ + // 1 * 8 = 8 + assert tree.sum(0, 7) == 8; + System.out.println("Tests passed"); + } +}