Skip to content

Commit bd4e402

Browse files
Added Fenwick Trees (#92)
1 parent 6517ea5 commit bd4e402

File tree

3 files changed

+141
-4
lines changed

3 files changed

+141
-4
lines changed

pydatastructs/trees/__init__.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,16 @@
22

33
from . import (
44
binary_trees,
5-
space_partitioning_trees
5+
space_partitioning_trees,
6+
heaps
67
)
78

89
from .binary_trees import (
9-
TreeNode, BinaryTree, BinarySearchTree, BinaryTreeTraversal, AVLTree
10+
BinaryTree,
11+
BinarySearchTree,
12+
BinaryTreeTraversal,
13+
AVLTree,
14+
BinaryIndexedTree
1015
)
1116
__all__.extend(binary_trees.__all__)
1217

pydatastructs/trees/binary_trees.py

Lines changed: 119 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
'AVLTree',
1111
'BinaryTree',
1212
'BinarySearchTree',
13-
'BinaryTreeTraversal'
13+
'BinaryTreeTraversal',
14+
'BinaryIndexedTree'
1415
]
1516

1617
class BinaryTree(object):
@@ -920,3 +921,120 @@ def breadth_first_search(self, node=None, strategy='queue'):
920921
if tree[node].right is not None:
921922
q.append(tree[node].right)
922923
return visit
924+
925+
class BinaryIndexedTree(object):
926+
"""
927+
Represents binary indexed trees
928+
a.k.a fenwick trees.
929+
930+
Parameters
931+
==========
932+
933+
array: list/tuple
934+
The array whose elements are to be
935+
considered for the queries.
936+
937+
Examples
938+
========
939+
940+
>>> from pydatastructs import BinaryIndexedTree
941+
>>> bit = BinaryIndexedTree([1, 2, 3])
942+
>>> bit.get_sum(0, 2)
943+
6
944+
>>> bit.update(0, 100)
945+
>>> bit.get_sum(0, 2)
946+
105
947+
948+
References
949+
==========
950+
951+
.. [1] https://en.wikipedia.org/wiki/Fenwick_tree
952+
"""
953+
954+
__slots__ = ['tree', 'array', 'flag']
955+
956+
def __new__(cls, array):
957+
958+
obj = object.__new__(cls)
959+
obj.array = OneDimensionalArray(type(array[0]), array)
960+
obj.tree = [0] * (obj.array._size + 2)
961+
obj.flag = [0] * (obj.array._size)
962+
for index in range(obj.array._size):
963+
obj.update(index, array[index])
964+
return obj
965+
966+
def update(self, index, value):
967+
"""
968+
Updates value at the given index.
969+
970+
Parameters
971+
==========
972+
973+
index: int
974+
Index of element to be updated.
975+
976+
value
977+
The value to be inserted.
978+
"""
979+
_index, _value = index, value
980+
if self.flag[index] == 0:
981+
self.flag[index] = 1
982+
index += 1
983+
while index < self.array._size + 1:
984+
self.tree[index] += value
985+
index = index + (index & (-index))
986+
else:
987+
value = value - self.array[index]
988+
index += 1
989+
while index < self.array._size + 1:
990+
self.tree[index] += value
991+
index = index + (index & (-index))
992+
self.array[_index] = _value
993+
994+
def get_prefix_sum(self, index):
995+
"""
996+
Computes sum of elements from index 0 to given index.
997+
998+
Parameters
999+
==========
1000+
1001+
index: int
1002+
Index till which sum has to be calculated.
1003+
1004+
Returns
1005+
=======
1006+
1007+
sum: int
1008+
The required sum.
1009+
"""
1010+
index += 1
1011+
sum = 0
1012+
while index > 0:
1013+
sum += self.tree[index]
1014+
index = index - (index & (-index))
1015+
return sum
1016+
1017+
def get_sum(self, left_index, right_index):
1018+
"""
1019+
Get sum of elements from left index to right index.
1020+
1021+
Parameters
1022+
==========
1023+
1024+
left_index: int
1025+
Starting index from where sum has to be computed.
1026+
1027+
right_index: int
1028+
Ending index till where sum has to be computed.
1029+
1030+
Returns
1031+
=======
1032+
1033+
sum: int
1034+
The required sum
1035+
"""
1036+
if left_index >= 1:
1037+
return self.get_prefix_sum(right_index) - \
1038+
self.get_prefix_sum(left_index - 1)
1039+
else:
1040+
return self.get_prefix_sum(right_index)

pydatastructs/trees/tests/test_binary_trees.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from pydatastructs.trees.binary_trees import (
22
BinarySearchTree, BinaryTreeTraversal, AVLTree,
3-
ArrayForTrees)
3+
ArrayForTrees, BinaryIndexedTree)
44
from pydatastructs.utils.raises_util import raises
55
from pydatastructs.utils.misc_util import TreeNode
66
from copy import deepcopy
@@ -305,3 +305,17 @@ def test_select_rank(expected_output):
305305
test_select_rank([2])
306306
a5.delete(2)
307307
test_select_rank([])
308+
309+
def test_BinaryIndexedTree():
310+
311+
FT = BinaryIndexedTree
312+
313+
t = FT([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
314+
315+
assert t.get_sum(0, 2) == 6
316+
assert t.get_sum(0, 4) == 15
317+
assert t.get_sum(0, 9) == 55
318+
t.update(0, 100)
319+
assert t.get_sum(0, 2) == 105
320+
assert t.get_sum(0, 4) == 114
321+
assert t.get_sum(1, 9) == 54

0 commit comments

Comments
 (0)