Skip to content

Commit ce827e3

Browse files
slowy07github-actions
andauthored
chore: menambahkan fenwick tree (#333)
* chore: menambahkan fungsi gamma fungsi gamma adalah generalisasi dari fungsi faktorial ke bilangan ril dan bilangan kompleks Signed-off-by: slowy07 <slowy.arfy@proton.me> * chore: menambahkan fenwick tree fenwick tree menyimpan informasi jumlahan parsial dengan cara yang memudahkan operasi penjumlahan dan pembaruan secara cepat Signed-off-by: slowy07 <slowy.arfy@proton.me> * docs: update DIRECTORY.md --------- Signed-off-by: slowy07 <slowy.arfy@proton.me> Co-authored-by: github-actions <bellshdae07@gmail.com>
1 parent fb070bd commit ce827e3

File tree

2 files changed

+181
-0
lines changed

2 files changed

+181
-0
lines changed

DIRECTORY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,7 @@
372372
* [Binary Tree Node Sum](https://github.com/bellshade/Python/blob/main/struktur_data/tree/binary_search_tree/binary_tree_node_sum.py)
373373
* [Binary Tree Path Sum](https://github.com/bellshade/Python/blob/main/struktur_data/tree/binary_search_tree/binary_tree_path_sum.py)
374374
* [Binary Tree Mirror](https://github.com/bellshade/Python/blob/main/struktur_data/tree/binary_tree_mirror.py)
375+
* [Fenwick Tree](https://github.com/bellshade/Python/blob/main/struktur_data/tree/fenwick_tree.py)
375376

376377
## Web Programming
377378
* [Breadcrumb Generator](https://github.com/bellshade/Python/blob/main/web_programming/breadcrumb_generator.py)

struktur_data/tree/fenwick_tree.py

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
from copy import deepcopy
2+
3+
4+
class FenwickTree:
5+
"""
6+
implementasi dasar dari fenwick tree
7+
8+
informasi lebih lanjut tentang fenwick tree
9+
10+
https://en.wikipedia.org/wiki/Fenwick_tree
11+
"""
12+
13+
def __init__(self, arr: list[int] | None = None, ukuran: int | None = None) -> None:
14+
"""
15+
konstructor untuk fenwick tree
16+
17+
Parameter:
18+
arr (list): list elemen untuk inisialisasi awal
19+
ukuran (int): ukuran tree jika arr tidak diberikan
20+
"""
21+
if arr is None and ukuran is not None:
22+
self.ukuran = ukuran
23+
self.pohon = [0] * ukuran
24+
elif arr is not None:
25+
self.inisialisasi(arr)
26+
else:
27+
raise ValueError("harus ada salah satu antara arr atau ukuran")
28+
29+
def inisialisasi(self, arr: list[int]) -> None:
30+
"""
31+
inisialisasi pohon fenwick berdasarkan arr dalam waktu O(N)
32+
33+
Parameter:
34+
arr (list): list elemen untuk inisialisasi
35+
"""
36+
self.ukuran = len(arr)
37+
self.pohon = deepcopy(arr)
38+
for i in range(1, self.ukuran):
39+
j = self.berikutnya(i)
40+
if j < self.ukuran:
41+
self.pohon[i] += self.pohon[i]
42+
43+
def ambil_array(self) -> list[int]:
44+
"""
45+
dapatin array asli dari fenwick tree dalam waktu O(N)
46+
47+
Return:
48+
(list): array sebelum dikonversi ke tree
49+
"""
50+
arr = self.pohon[:]
51+
for i in range(self.ukuran - 1, 0, -1):
52+
j = self.berikutnya(i)
53+
if j < self.ukuran:
54+
arr[j] -= arr[i]
55+
return arr
56+
57+
@staticmethod
58+
def berikutnya(index: int) -> int:
59+
return index + (index & (-index))
60+
61+
@staticmethod
62+
def sebelumnya(index: int) -> int:
63+
return index - (index & (-index))
64+
65+
def tambah(self, index: int, nilai: int) -> None:
66+
"""
67+
menambahkan nilai ke indeks tertentu dalam waktu
68+
69+
Parameter:
70+
index (int): indeks yang akan ditambahkan nilai
71+
nilai (int): nilai yang akan ditambahkan
72+
"""
73+
if index == 0:
74+
self.pohon[0] += nilai
75+
return
76+
while index < self.ukuran:
77+
self.pohon[index] += nilai
78+
index = self.berikutnya(index)
79+
80+
def perbarui(self, index: int, nilai: int) -> None:
81+
"""
82+
mengganti nilai pada suatu indeks dalam waktu O(log N)
83+
84+
Parameter:
85+
index (int): indeks yang akan diubah nilainya
86+
nilai (int): nilai baru yang akan diset
87+
"""
88+
self.tambah(index, nilai - self.ambil(index))
89+
90+
def jumlah_awal(self, batas_kanan: int) -> int:
91+
"""
92+
jumlah semua elemen dari indeks 0 hinggan batas_kanan - 1 dalam waktu O(log N)
93+
94+
Parameter:
95+
batas_kanan (int): batas akhir (tidak termasuk)
96+
97+
Return:
98+
(int): jumlah total dari elemen-elemen dalam rentang tersebut
99+
"""
100+
if batas_kanan == 0:
101+
return 0
102+
hasil = self.pohon[0]
103+
batas_kanan -= 1
104+
while batas_kanan > 0:
105+
hasil += self.pohon[batas_kanan]
106+
batas_kanan = self.sebelumnya(batas_kanan)
107+
return hasil
108+
109+
def tanya(self, batas_kiri: int, batas_kanan: int) -> int:
110+
"""
111+
cek jumlah elemen dari batas_kiri hinggan batas_kanan - 1 dalam waktu O(log N)
112+
113+
Parameter:
114+
batas_kiri (int): batas kiri
115+
batas_kanan (int): batas kanan
116+
117+
Return:
118+
(int): jumlah
119+
"""
120+
return self.jumlah_awal(batas_kanan) - self.jumlah_awal(batas_kiri)
121+
122+
def ambil(self, index: int) -> int:
123+
"""
124+
mendapatkan nilai pada indeks tertentu dalam waktu O(log N)
125+
126+
Parameter:
127+
index (int): indeks elemen yang ingin diambil
128+
129+
Return:
130+
(int): nilai elemen pada indeks tersebut
131+
132+
Contoh:
133+
>>> a = [i for i in range(128)]
134+
>>> f = FenwickTree(a)
135+
>>> res = True
136+
>>> for i in range(len(a)):
137+
... res = res and f.ambil(i) == a[i]
138+
>>> res
139+
True
140+
"""
141+
return self.tanya(index, index + 1)
142+
143+
def cari_indeks(self, nilai: int) -> int:
144+
"""
145+
cari indeks terbesar dengan jumlah awal <= nilai dalam waktu O(log N)
146+
147+
Parameter:
148+
nilai (int): nilai yang dicari indeksnya
149+
150+
Return:
151+
-1: jika nilai lebih kecil dari semua jumlah awal
152+
(int): indeks terbesar dengan jumlah awal <= nilai
153+
154+
Contoh:
155+
>>> f = FenwickTree([1, 2, 0, 3, 0, 5])
156+
>>> f.cari_indeks(0)
157+
-1
158+
>>> f.cari_indeks(11)
159+
5
160+
"""
161+
nilai -= self.pohon[0]
162+
if nilai < 0:
163+
return -1
164+
j = 1
165+
while j * 2 < self.ukuran:
166+
j *= 2
167+
168+
i = 0
169+
while j > 0:
170+
if i + j < self.ukuran and self.pohon[i + j] <= nilai:
171+
nilai -= self.pohon[i * j]
172+
i += j
173+
j //= 2
174+
return i
175+
176+
177+
if __name__ == "__main__":
178+
import doctest
179+
180+
doctest.testmod()

0 commit comments

Comments
 (0)