MyCaffe  1.12.2.41
Deep learning software for Windows C# programmers.
SegmentTree.cs
1using System;
2using System.Collections.Generic;
3using System.Diagnostics;
4using System.Linq;
5using System.Text;
6using System.Threading.Tasks;
7
9{
24 public class SegmentTree
25 {
29 protected int m_nCapacity;
33 protected OPERATION m_op;
37 protected double[] m_rgfValues;
38
42 public enum OPERATION
43 {
47 SUM,
51 MIN
52 }
53
60 public SegmentTree(int nCapacity, OPERATION oper, float fNeutralElement)
61 {
62 if (nCapacity <= 0 || (nCapacity % 2) != 0)
63 throw new Exception("The capacity must be positive and a power of 2.");
64
65 m_nCapacity = nCapacity;
66 m_op = oper;
67 m_rgfValues = new double[2 * nCapacity];
68
69 for (int i = 0; i < m_rgfValues.Length; i++)
70 {
71 m_rgfValues[i] = fNeutralElement;
72 }
73 }
74
75 private double operation(double f1, double f2)
76 {
77 switch (m_op)
78 {
79 case OPERATION.MIN:
80 return Math.Min(f1, f2);
81
82 case OPERATION.SUM:
83 return f1 + f2;
84
85 default:
86 throw new Exception("Unknown operation '" + m_op.ToString() + "'!");
87 }
88 }
89
90 private double reduce_helper(int nStart, int nEnd, int nNode, int nNodeStart, int nNodeEnd)
91 {
92 if (nEnd < 0)
93 {
94 Trace.WriteLine("**SegmentTree: nEnd is less than zero and should not be.");
95 return m_rgfValues[nNode];
96 }
97
98 if (nStart == nNodeStart && nEnd == nNodeEnd)
99 return m_rgfValues[nNode];
100
101 int nMid = (nNodeStart + nNodeEnd) / 2;
102
103 if (nEnd <= nMid)
104 {
105 return reduce_helper(nStart, nEnd, 2 * nNode, nNodeStart, nMid);
106 }
107 else
108 {
109 if (nMid + 1 <= nStart)
110 {
111 return reduce_helper(nStart, nMid, 2 * nNode + 1, nMid + 1, nNodeEnd);
112 }
113 else
114 {
115 double f1 = reduce_helper(nStart, nMid, 2 * nNode, nNodeStart, nMid);
116 double f2 = reduce_helper(nMid + 1, nEnd, 2 * nNode + 1, nMid + 1, nNodeEnd);
117 return operation(f1, f2);
118 }
119 }
120 }
121
129 public double reduce(int nStart, int? nEnd = null)
130 {
131 if (!nEnd.HasValue)
132 nEnd = m_nCapacity;
133
134 if (nEnd < 0)
135 nEnd += m_nCapacity;
136
137 nEnd -= 1;
138
139 return reduce_helper(nStart, nEnd.Value, 1, 0, m_nCapacity - 1);
140 }
141
147 public double this[int nIdx]
148 {
149 get
150 {
151 if (nIdx < 0 || nIdx >= m_nCapacity)
152 throw new Exception("The index is out of range!");
153
154 return m_rgfValues[m_nCapacity + nIdx];
155 }
156 set
157 {
158 nIdx += m_nCapacity;
159 m_rgfValues[nIdx] = value;
160
161 nIdx /= 2;
162
163 while (nIdx >= 1)
164 {
165 m_rgfValues[nIdx] = operation(m_rgfValues[2 * nIdx], m_rgfValues[2 * nIdx + 1]);
166 nIdx /= 2;
167 }
168 }
169 }
170 }
171
176 {
181 public SumSegmentTree(int nCapacity)
182 : base(nCapacity, OPERATION.SUM, 0.0f)
183 {
184 }
185
192 public double sum(int nStart = 0, int? nEnd = null)
193 {
194 return reduce(nStart, nEnd);
195 }
196
205 public int find_prefixsum_idx(double fPrefixSum)
206 {
207 if (fPrefixSum < 0)
208 throw new Exception("The prefix sum must be greater than zero.");
209
210 double fSum = sum() + 1e-5;
211 if (fPrefixSum > fSum)
212 throw new Exception("The prefix sum cannot exceed the overall sum of '" + fSum.ToString() + "'!");
213
214 int nIdx = 1;
215 while (nIdx < m_nCapacity) // while non-leaf
216 {
217 if (m_rgfValues[2 * nIdx] > fPrefixSum)
218 {
219 nIdx = 2 * nIdx;
220 }
221 else
222 {
223 fPrefixSum -= m_rgfValues[2 * nIdx];
224 nIdx = 2 * nIdx + 1;
225 }
226 }
227
228 return nIdx - m_nCapacity;
229 }
230 }
231
236 {
241 public MinSegmentTree(int nCapacity)
242 : base(nCapacity, OPERATION.MIN, float.MaxValue)
243 {
244 }
245
252 public double min(int nStart = 0, int? nEnd = null)
253 {
254 return reduce(nStart, nEnd);
255 }
256 }
257}
The MinSegmentTree performs a reduction over the array and returns the minimum value.
Definition: SegmentTree.cs:236
MinSegmentTree(int nCapacity)
The constructor.
Definition: SegmentTree.cs:241
double min(int nStart=0, int? nEnd=null)
Returns the minimum element in the array.
Definition: SegmentTree.cs:252
Segment tree data structure
Definition: SegmentTree.cs:25
int m_nCapacity
Specifies the capacity of the segment tree.
Definition: SegmentTree.cs:29
SegmentTree(int nCapacity, OPERATION oper, float fNeutralElement)
The constructor.
Definition: SegmentTree.cs:60
double[] m_rgfValues
Specifies the data of the tree.
Definition: SegmentTree.cs:37
OPERATION m_op
Specifies the operation to perform when reducing the tree.
Definition: SegmentTree.cs:33
double reduce(int nStart, int? nEnd=null)
Returns result of applying self.operation to a contiguous subsequence of the array....
Definition: SegmentTree.cs:129
OPERATION
Specifies the operations used during the reduction.
Definition: SegmentTree.cs:43
The SumSegmentTree provides a sum reduction of the items within the array.
Definition: SegmentTree.cs:176
int find_prefixsum_idx(double fPrefixSum)
Finds the highest indes 'i' in the array such that sum(arr[0] + arr[1] + ... + arr[i-1]) less than or...
Definition: SegmentTree.cs:205
SumSegmentTree(int nCapacity)
The constructor.
Definition: SegmentTree.cs:181
double sum(int nStart=0, int? nEnd=null)
Returns arr[start] + ... + arr[end]
Definition: SegmentTree.cs:192