Skip to content

Commit 5867186

Browse files
authored
algorithm: SegmentTree (TheAlgorithms#1178)
1 parent 636017c commit 5867186

File tree

2 files changed

+113
-0
lines changed

2 files changed

+113
-0
lines changed

Data-Structures/Tree/SegmentTree.js

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/**
2+
* Segment Tree
3+
* concept : [Wikipedia](https://en.wikipedia.org/wiki/Segment_tree)
4+
* inspired by : https://www.geeksforgeeks.org/segment-tree-efficient-implementation/
5+
*
6+
* time complexity
7+
* - init : O(N)
8+
* - update : O(log(N))
9+
* - query : O(log(N))
10+
*
11+
* space complexity : O(N)
12+
*/
13+
class SegmentTree {
14+
size
15+
tree
16+
constructor (arr) {
17+
// we define tree like this
18+
// tree[1] : root node of tree
19+
// tree[i] : i'th node
20+
// tree[i * 2] : i'th left child
21+
// tree[i * 2 + 1] : i'th right child
22+
// and we use bit, shift operation for index
23+
this.size = arr.length
24+
this.tree = new Array(2 * arr.length)
25+
this.tree.fill(0)
26+
27+
this.build(arr)
28+
}
29+
30+
// function to build the tree
31+
build (arr) {
32+
const { size, tree } = this
33+
// insert leaf nodes in tree
34+
// leaf nodes will start from index N
35+
// in this array and will go up to index (2 * N – 1)
36+
for (let i = 0; i < size; i++) {
37+
tree[size + i] = arr[i]
38+
}
39+
40+
// build the tree by calculating parents
41+
// tree's root node will contain all leaf node's sum
42+
for (let i = size - 1; i > 0; --i) {
43+
// current node's value is the sum of left child, right child
44+
tree[i] = tree[i * 2] + tree[i * 2 + 1]
45+
}
46+
}
47+
48+
update (index, value) {
49+
const { size, tree } = this
50+
51+
// only update values in the parents of the given node being changed.
52+
// to get the parent move to parent node (index / 2)
53+
54+
// set value at position index
55+
index += size
56+
// tree[index] is leaf node and index's value of array
57+
tree[index] = value
58+
59+
// move upward and update parents
60+
for (let i = index; i > 1; i >>= 1) {
61+
// i ^ 1 turns (2 * i) to (2 * i + 1)
62+
// i ^ 1 is second child
63+
tree[i >> 1] = tree[i] + tree[i ^ 1]
64+
}
65+
}
66+
67+
// interval [L,R) with left index(L) included and right (R) excluded.
68+
query (left, right) {
69+
const { size, tree } = this
70+
// cause R is excluded, increase right for convenient
71+
right++
72+
let res = 0
73+
74+
// loop to find the sum in the range
75+
for (left += size, right += size; left < right; left >>= 1, right >>= 1) {
76+
// L is the left border of an query interval
77+
78+
// if L is odd it means that it is the right child of its parent and our interval includes only L and not the parent.
79+
// So we will simply include this node to sum and move to the parent of its next node by doing L = (L + 1) / 2.
80+
81+
// if L is even it is the left child of its parent
82+
// and the interval includes its parent also unless the right borders interfere.
83+
if ((left & 1) > 0) {
84+
res += tree[left++]
85+
}
86+
87+
// same in R (the right border of an query interval)
88+
if ((right & 1) > 0) {
89+
res += tree[--right]
90+
}
91+
}
92+
93+
return res
94+
}
95+
}
96+
97+
export { SegmentTree }
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { SegmentTree } from '../SegmentTree'
2+
3+
describe('SegmentTree sum test', () => {
4+
const a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
5+
6+
const segment = new SegmentTree(a)
7+
8+
it('init sum check', () => {
9+
expect(segment.query(0, 2)).toBe(6)
10+
})
11+
12+
it('init sum check', () => {
13+
segment.update(2, 1)
14+
expect(segment.query(0, 2)).toBe(4)
15+
})
16+
})

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy