|
NCBI Home IEB Home C++ Toolkit docs C Toolkit source browser C Toolkit source browser (2) |
NCBI C++ Toolkit Cross ReferenceC++/src/util/itree.cpp |
source navigation diff markup identifier search freetext search file search |
1 /* $Id: itree.cpp 103491 2007-05-04 17:18:18Z kazimird $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Author: Eugene Vasilchenko
27 *
28 * File Description:
29 * Implementation of interval search tree.
30 *
31 * ===========================================================================
32 */
33
34 #include <ncbi_pch.hpp>
35 #include <corelib/ncbistd.hpp>
36 #include <util/itree.hpp>
37
38 BEGIN_NCBI_SCOPE
39
40 inline
41 CIntervalTree::coordinate_type CIntervalTree::GetMaxRootCoordinate(void) const
42 {
43 coordinate_type max = m_Root.m_Key * 2;
44 if ( max <= 0 )
45 max = TTraits::GetMaxCoordinate();
46 return max;
47 }
48
49 inline
50 CIntervalTree::coordinate_type CIntervalTree::GetNextRootKey(void) const
51 {
52 coordinate_type nextKey = m_Root.m_Key * 2;
53 _ASSERT(nextKey > 0);
54 return nextKey;
55 }
56
57 void CIntervalTree::DoInsert(const interval_type& interval, TTreeMapI value)
58 {
59 _ASSERT(TTraits::IsNormal(interval));
60
61 // ensure our tree covers specified interval
62 if ( interval.GetTo() > GetMaxRootCoordinate() ) {
63 // insert one more level on top
64 if ( m_Root.m_Left || m_Root.m_Right || m_Root.m_NodeIntervals ) {
65 // non empty tree, insert new root node
66 do {
67 TTreeNode* newLeft = AllocNode();
68 // copy root node contents
69 *newLeft = m_Root;
70 // fill new root
71 m_Root.m_Key = GetNextRootKey();
72 m_Root.m_Left = newLeft;
73 m_Root.m_Right = 0;
74 m_Root.m_NodeIntervals = 0;
75 } while ( interval.GetTo() > GetMaxRootCoordinate() );
76 }
77 else {
78 // empty tree, just recalculate root
79 do {
80 m_Root.m_Key = GetNextRootKey();
81 } while ( interval.GetTo() > GetMaxRootCoordinate() );
82 }
83 }
84
85 TTreeNode* node = &m_Root;
86 coordinate_type nodeSize = m_Root.m_Key;
87 for ( ;; ) {
88 coordinate_type key = node->m_Key;
89 nodeSize = (nodeSize + 1) / 2;
90
91 TTreeNode** nextPtr;
92 coordinate_type nextKeyOffset;
93
94 if ( interval.GetFrom() > key ) {
95 nextPtr = &node->m_Right;
96 nextKeyOffset = nodeSize;
97 }
98 else if ( interval.GetTo() < key ) {
99 nextPtr = &node->m_Left;
100 nextKeyOffset = -nodeSize;
101 }
102 else {
103 // found our tile
104 TTreeNodeInts* nodeIntervals = node->m_NodeIntervals;
105 if ( !nodeIntervals )
106 node->m_NodeIntervals = nodeIntervals = CreateNodeIntervals();
107 nodeIntervals->Insert(interval, value);
108 return;
109 }
110
111 TTreeNode* next = *nextPtr;
112 if ( !next ) // create new node
113 (*nextPtr) = next = InitNode(AllocNode(), key + nextKeyOffset);
114
115 _ASSERT(next->m_Key == key + nextKeyOffset);
116 node = next;
117 }
118 }
119
120 bool CIntervalTree::DoDelete(TTreeNode* node, const interval_type& interval,
121 TTreeMapI value)
122 {
123 _ASSERT(node);
124 coordinate_type key = node->m_Key;
125 if ( interval.GetFrom() > key ) {
126 // left
127 return DoDelete(node->m_Right, interval, value) &&
128 !node->m_NodeIntervals && !node->m_Left;
129 }
130 else if ( interval.GetTo() < key ) {
131 // right
132 return DoDelete(node->m_Left, interval, value) &&
133 !node->m_NodeIntervals && !node->m_Right;
134 }
135 else {
136 // inside
137 TTreeNodeInts* nodeIntervals = node->m_NodeIntervals;
138 _ASSERT(nodeIntervals);
139
140 if ( !nodeIntervals->Delete(interval, value) )
141 return false; // node intervals non empty
142
143 // remove node intervals
144 DeleteNodeIntervals(nodeIntervals);
145 node->m_NodeIntervals = 0;
146
147 // delete node if it doesn't have leaves
148 return !node->m_Left && !node->m_Right;
149 }
150 }
151
152 void CIntervalTree::Destroy(void)
153 {
154 ClearNode(&m_Root);
155 m_ByX.clear();
156 }
157
158 CIntervalTree::iterator CIntervalTree::Insert(const interval_type& interval,
159 const mapped_type& value)
160 {
161 TTreeMapI iter = m_ByX.insert(TTreeMapValue(interval.GetFrom(),
162 interval.GetTo(),
163 value));
164 DoInsert(interval, iter);
165
166 return iterator(0, TTraits::GetMaxCoordinate(), &TTreeMap::get(iter));
167 }
168
169 CIntervalTree::const_iterator
170 CIntervalTree::IntervalsOverlapping(const interval_type& interval) const
171 {
172 coordinate_type x = interval.GetFrom();
173 coordinate_type y = interval.GetTo();
174
175 const_iterator it(x, TTraits::GetMaxCoordinate(), 0, &m_Root);
176
177 TTreeMapCI iter =
178 m_ByX.lower_bound(TTreeMapValue(x + 1, 0, mapped_type()));
179 if ( iter != m_ByX.end() && iter->GetKey() <= y ) {
180 it.m_SearchLimit = y;
181 it.m_CurrentMapValue = &*iter;
182 }
183 else {
184 it.NextLevel();
185 }
186 return it;
187 }
188
189 CIntervalTree::iterator
190 CIntervalTree::IntervalsOverlapping(const interval_type& interval)
191 {
192 coordinate_type x = interval.GetFrom();
193 coordinate_type y = interval.GetTo();
194
195 iterator it(x, TTraits::GetMaxCoordinate(), 0, &m_Root);
196
197 TTreeMapI iter =
198 m_ByX.lower_bound(TTreeMapValue(x + 1, 0, mapped_type()));
199 if ( iter != m_ByX.end() && iter->GetKey() <= y ) {
200 it.m_SearchLimit = y;
201 it.m_CurrentMapValue = &TTreeMap::get(iter);
202 }
203 else {
204 it.NextLevel();
205 }
206 return it;
207 }
208
209 CIntervalTree::TTreeNode* CIntervalTree::AllocNode(void)
210 {
211 return m_NodeAllocator.allocate(1, (TTreeNode*) 0);
212 }
213
214 void CIntervalTree::DeallocNode(TTreeNode* node)
215 {
216 m_NodeAllocator.deallocate(node, 1);
217 }
218
219 CIntervalTree::TTreeNodeInts* CIntervalTree::AllocNodeIntervals(void)
220 {
221 return m_NodeIntervalsAllocator.allocate(1, (TTreeNodeInts*) 0);
222 }
223
224 void CIntervalTree::DeallocNodeIntervals(TTreeNodeInts* ptr)
225 {
226 m_NodeIntervalsAllocator.deallocate(ptr, 1);
227 }
228
229 CIntervalTree::TTreeNodeInts* CIntervalTree::CreateNodeIntervals(void)
230 {
231 TTreeNodeInts* ints = new (AllocNodeIntervals())TTreeNodeInts();
232 #if defined(_RWSTD_VER) && !defined(_RWSTD_STRICT_ANSI)
233 ints->m_ByX.allocation_size(16);
234 ints->m_ByY.allocation_size(16);
235 #endif
236 return ints;
237 }
238
239 void CIntervalTree::DeleteNodeIntervals(TTreeNodeInts* ptr)
240 {
241 if ( ptr ) {
242 ptr->~TTreeNodeInts();
243 DeallocNodeIntervals(ptr);
244 }
245 }
246
247 void CIntervalTree::ClearNode(TTreeNode* node)
248 {
249 DeleteNodeIntervals(node->m_NodeIntervals);
250
251 DeleteNode(node->m_Left);
252 DeleteNode(node->m_Right);
253 node->m_Left = node->m_Right = 0;
254 }
255
256 pair<double, CIntervalTree::size_type> CIntervalTree::Stat(void) const
257 {
258 SStat stat;
259 stat.total = stat.count = stat.max = 0;
260 Stat(&m_Root, stat);
261 return make_pair(double(stat.total) / stat.count, stat.max);
262 }
263
264 void CIntervalTree::Stat(const TTreeNode* node, SStat& stat) const
265 {
266 if ( !node )
267 return;
268
269 if ( node->m_NodeIntervals ) {
270 size_type len = node->m_NodeIntervals->m_ByX.size();
271 ++stat.count;
272 stat.total += len;
273 stat.max = max(stat.max, len);
274 }
275
276 Stat(node->m_Right, stat);
277 Stat(node->m_Left, stat);
278 }
279
280 END_NCBI_SCOPE
281 |
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more information. |