|
10 | 10 | 'AVLTree', |
11 | 11 | 'BinaryTree', |
12 | 12 | 'BinarySearchTree', |
13 | | - 'BinaryTreeTraversal' |
| 13 | + 'BinaryTreeTraversal', |
| 14 | + 'BinaryIndexedTree' |
14 | 15 | ] |
15 | 16 |
|
16 | 17 | class BinaryTree(object): |
@@ -920,3 +921,120 @@ def breadth_first_search(self, node=None, strategy='queue'): |
920 | 921 | if tree[node].right is not None: |
921 | 922 | q.append(tree[node].right) |
922 | 923 | 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) |
0 commit comments