mirror of
https://github.moeyy.xyz/https://github.com/trekhleb/javascript-algorithms.git
synced 2024-12-26 23:21:18 +08:00
Added Binary Indexed Tree / Fenwick Tree Implementation (#51)
* added fenwick tree implementation * added fenwick tree implementation
This commit is contained in:
parent
a1060c2a94
commit
1a4fe11a80
49
src/data-structures/tree/fenwick-tree/FenwickTree.js
Normal file
49
src/data-structures/tree/fenwick-tree/FenwickTree.js
Normal file
@ -0,0 +1,49 @@
|
||||
export default class FenwickTree {
|
||||
/**
|
||||
* Constructor creates empty fenwick tree of size 'size',
|
||||
* however, array size is size+1, because index is 1-based
|
||||
* @param {number} [size]
|
||||
*/
|
||||
constructor(size) {
|
||||
this.n = size;
|
||||
this.arr = [];
|
||||
for (let i = 0; i <= size; i += 1) this.arr.push(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds v to index x
|
||||
* @param {number} [x]
|
||||
* @param {number} [v]
|
||||
*/
|
||||
update(x, v) {
|
||||
if (x < 1 || x > this.n) return;
|
||||
for (let i = x; i <= this.n; i += (i & -i)) {
|
||||
this.arr[i] += v;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* query sum from index 1 to x
|
||||
* @param {number} [x]
|
||||
* @return {number} sum
|
||||
*/
|
||||
query(x) {
|
||||
if (x > this.n) return this.query(this.n);
|
||||
let ret = 0;
|
||||
for (let i = x; i > 0; i -= (i & -i)) {
|
||||
ret += this.arr[i];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* query sum from index l to r
|
||||
* @param {number} [l]
|
||||
* @param {number} [r]
|
||||
* @return {number}
|
||||
*/
|
||||
queryRange(l, r) {
|
||||
if (l > r) return 0;
|
||||
return this.query(r) - this.query(l - 1);
|
||||
}
|
||||
}
|
8
src/data-structures/tree/fenwick-tree/README.md
Normal file
8
src/data-structures/tree/fenwick-tree/README.md
Normal file
@ -0,0 +1,8 @@
|
||||
# Binary Indexed Tree / Fenwick Tree
|
||||
|
||||
A simple data structure that supports fast range queries in an array. However, it is usually only valid for reversible operations, like addition and subtraction
|
||||
|
||||
This implementation uses the basic range sum query and point update. All the indexes are 1-based
|
||||
|
||||
- [Wikipedia](https://en.wikipedia.org/wiki/Fenwick_tree)
|
||||
- [Geeksforgeeks](https://www.geeksforgeeks.org/binary-indexed-tree-or-fenwick-tree-2/)
|
@ -0,0 +1,37 @@
|
||||
import FenwickTree from '../FenwickTree';
|
||||
|
||||
describe('FenwickTree', () => {
|
||||
it('should create empty fenwick tree of correct size', () => {
|
||||
const tree1 = new FenwickTree(5);
|
||||
expect(tree1.arr.length).toBe(5 + 1);
|
||||
|
||||
for (let i = 0; i < 5; i += 1) {
|
||||
expect(tree1.arr[i]).toBe(0);
|
||||
}
|
||||
|
||||
const tree2 = new FenwickTree(50);
|
||||
expect(tree2.arr.length).toBe(50 + 1);
|
||||
});
|
||||
|
||||
it('should correctly execute queries', () => {
|
||||
const tree = new FenwickTree(5);
|
||||
|
||||
tree.update(1, 4);
|
||||
tree.update(3, 7);
|
||||
|
||||
expect(tree.query(1)).toBe(4);
|
||||
expect(tree.query(3)).toBe(11);
|
||||
expect(tree.query(5)).toBe(11);
|
||||
expect(tree.queryRange(2, 3)).toBe(7);
|
||||
|
||||
tree.update(2, 5);
|
||||
expect(tree.query(5)).toBe(16);
|
||||
|
||||
tree.update(1, 3);
|
||||
expect(tree.queryRange(1, 1)).toBe(7);
|
||||
expect(tree.query(5)).toBe(19);
|
||||
expect(tree.queryRange(1, 5)).toBe(19);
|
||||
|
||||
expect(tree.queryRange(5, 1)).toBe(0); // invalid test
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user