patternpythonMinor
Segment tree in Python3
Viewed 0 times
segmentpython3tree
Problem
I've implemented a Segment Tree in Python3:
```
import math
INF = int(2e9)
class SegmentTreeNode:
def __init__(self, l, r, v=INF):
self.left = l
self.right = r
self.value = v
def merge(self, left, right):
if left is not None and right is not None:
self.value = min(left.value, right.value)
elif left is None and right is None:
self.value = INF
elif left is None:
self.value = right.value
else:
self.value = left.value
class SegmentTree:
def __init__(self, a):
n = len(a)
power = math.ceil(math.log(n, 2))
total = 2 ** (power + 1)
self.__tree = [None] * int(total)
self.__leaf_length = int(total/2)-1
self.__build(1, 0, self.__leaf_length, a)
def __build(self, node, l, r, a):
if l == r:
self.__tree[node] = SegmentTreeNode(l, r)
try:
self.__tree[node].value = a[l]
except IndexError:
self.__tree[node].value = INF
return
leftchild = 2 * node
rightchild = leftchild + 1
mid = (l + r) // 2
self.__build(leftchild, l, mid, a)
self.__build(rightchild, mid + 1, r, a)
self.__tree[node] = SegmentTreeNode(l, r)
l = self.__tree[leftchild]
r = self.__tree[rightchild]
self.__tree[node].merge(l, r)
def __query(self, node, l, r, i, j):
if l >= i and r r:
return None
else:
leftchild = 2 * node
rightchild = leftchild + 1
mid = (l + r) // 2
l = self.__query(leftchild, l, mid, i, j)
r = self.__query(rightchild, mid + 1, r, i, j)
if l is not None and r is not None:
return SegmentTreeNode(-1, -1, min(l.value, r.value))
elif l is None and r is None:
return SegmentTreeNode(-1, -1, INF)
elif l is None:
```
import math
INF = int(2e9)
class SegmentTreeNode:
def __init__(self, l, r, v=INF):
self.left = l
self.right = r
self.value = v
def merge(self, left, right):
if left is not None and right is not None:
self.value = min(left.value, right.value)
elif left is None and right is None:
self.value = INF
elif left is None:
self.value = right.value
else:
self.value = left.value
class SegmentTree:
def __init__(self, a):
n = len(a)
power = math.ceil(math.log(n, 2))
total = 2 ** (power + 1)
self.__tree = [None] * int(total)
self.__leaf_length = int(total/2)-1
self.__build(1, 0, self.__leaf_length, a)
def __build(self, node, l, r, a):
if l == r:
self.__tree[node] = SegmentTreeNode(l, r)
try:
self.__tree[node].value = a[l]
except IndexError:
self.__tree[node].value = INF
return
leftchild = 2 * node
rightchild = leftchild + 1
mid = (l + r) // 2
self.__build(leftchild, l, mid, a)
self.__build(rightchild, mid + 1, r, a)
self.__tree[node] = SegmentTreeNode(l, r)
l = self.__tree[leftchild]
r = self.__tree[rightchild]
self.__tree[node].merge(l, r)
def __query(self, node, l, r, i, j):
if l >= i and r r:
return None
else:
leftchild = 2 * node
rightchild = leftchild + 1
mid = (l + r) // 2
l = self.__query(leftchild, l, mid, i, j)
r = self.__query(rightchild, mid + 1, r, i, j)
if l is not None and r is not None:
return SegmentTreeNode(-1, -1, min(l.value, r.value))
elif l is None and r is None:
return SegmentTreeNode(-1, -1, INF)
elif l is None:
Solution
SegmentTreeNode objects have three attributes: left, right and value, but only value is ever used. Using plain integers instead of custom objects should speed things up, as it avoids overhead both in object creation and in attribute access.Context
StackExchange Code Review Q#47596, answer score: 5
Revisions (0)
No revisions yet.