]>
git.ipfire.org Git - thirdparty/squid.git/blob - include/splay.h
4 #if defined(__cplusplus)
16 typedef int SPLAYCMP(Value
const &a
, Value
const &b
);
17 typedef void SPLAYFREE(Value
&);
18 typedef void SPLAYWALKEE(Value
const & nodedata
, void *state
);
19 static void DefaultFree (Value
&aValue
) {delete aValue
;}
21 SplayNode
<V
> (Value
const &);
23 mutable SplayNode
<V
> *left
;
24 mutable SplayNode
<V
> *right
;
25 void destroy(SPLAYFREE
*);
26 void walk(SPLAYWALKEE
*, void *callerState
);
27 bool empty() const { return this == NULL
; }
28 SplayNode
<V
> const * start() const;
29 SplayNode
<V
> const * finish() const;
31 SplayNode
<V
> * remove(const Value data
, SPLAYCMP
* compare
);
33 SplayNode
<V
> * insert(Value data
, SPLAYCMP
* compare
);
35 template <class FindValue
> SplayNode
<V
> * splay(const FindValue
&data
, int( * compare
)(FindValue
const &a
, Value
const &b
)) const;
38 typedef SplayNode
<void *> splayNode
;
41 class SplayConstIterator
;
52 typedef int SPLAYCMP(Value
const &a
, Value
const &b
);
53 typedef void SPLAYFREE(Value
&);
54 typedef SplayIterator
<V
> iterator
;
55 typedef const SplayConstIterator
<V
> const_iterator
;
56 Splay():head(NULL
), elements (0) {}
58 mutable SplayNode
<V
> * head
;
59 template <class FindValue
> Value
const *find (FindValue
const &, int( * compare
)(FindValue
const &a
, Value
const &b
)) const;
60 void insert(Value
const &, SPLAYCMP
*compare
);
62 void remove(Value
const &, SPLAYCMP
*compare
);
64 void destroy(SPLAYFREE
*);
66 SplayNode
<V
> const * start() const;
68 SplayNode
<V
> const * finish() const;
72 const_iterator
begin() const;
74 const_iterator
end() const;
79 SQUIDCEXTERN
int splayLastResult
;
81 SQUIDCEXTERN splayNode
*splay_insert(void *, splayNode
*, splayNode::SPLAYCMP
*);
83 SQUIDCEXTERN splayNode
*splay_delete(const void *, splayNode
*, splayNode::SPLAYCMP
*);
85 SQUIDCEXTERN splayNode
*splay_splay(const void **, splayNode
*, splayNode::SPLAYCMP
*);
87 SQUIDCEXTERN
void splay_destroy(splayNode
*, splayNode::SPLAYFREE
*);
89 SQUIDCEXTERN
void splay_walk(splayNode
*, splayNode::SPLAYWALKEE
*, void *callerState
);
93 SplayNode
<V
>::SplayNode (Value
const &someData
) : data(someData
), left(NULL
), right (NULL
) {}
97 SplayNode
<V
>::walk(SPLAYWALKEE
* walkee
, void *state
)
103 left
->walk(walkee
, state
);
108 right
->walk(walkee
, state
);
113 SplayNode
<V
>::start() const
116 return left
->start();
123 SplayNode
<V
>::finish() const
126 return right
->finish();
133 SplayNode
<V
>::destroy(SPLAYFREE
* free_func
)
139 left
->destroy(free_func
);
142 right
->destroy(free_func
);
151 SplayNode
<V
>::remove(Value
const dataToRemove
, SPLAYCMP
* compare
)
156 SplayNode
<V
> *result
= splay(dataToRemove
, compare
);
158 if (splayLastResult
== 0) { /* found it */
159 SplayNode
<V
> *newTop
;
161 if (result
->left
== NULL
) {
162 newTop
= result
->right
;
164 newTop
= result
->left
->splay(dataToRemove
, compare
);
166 newTop
->right
= result
->right
;
167 result
->right
= NULL
;
174 return result
; /* It wasn't there */
179 SplayNode
<V
>::insert(Value dataToInsert
, SPLAYCMP
* compare
)
181 /* create node to insert */
182 SplayNode
<V
> *newNode
= new SplayNode
<V
>(dataToInsert
);
185 splayLastResult
= -1;
186 newNode
->left
= newNode
->right
= NULL
;
190 SplayNode
<V
> *newTop
= splay(dataToInsert
, compare
);
192 if (splayLastResult
< 0) {
193 newNode
->left
= newTop
->left
;
194 newNode
->right
= newTop
;
197 } else if (splayLastResult
> 0) {
198 newNode
->right
= newTop
->right
;
199 newNode
->left
= newTop
;
200 newTop
->right
= NULL
;
203 /* duplicate entry */
210 template<class FindValue
>
212 SplayNode
<V
>::splay(FindValue
const &dataToFind
, int( * compare
)(FindValue
const &a
, Value
const &b
)) const
215 /* can't have compared successfully :} */
216 splayLastResult
= -1;
220 Value temp
= Value();
221 SplayNode
<V
> N(temp
);
225 N
.left
= N
.right
= NULL
;
228 SplayNode
<V
> *top
= const_cast<SplayNode
<V
> *>(this);
231 splayLastResult
= compare(dataToFind
, top
->data
);
233 if (splayLastResult
< 0) {
234 if (top
->left
== NULL
)
237 if ((splayLastResult
= compare(dataToFind
, top
->left
->data
)) < 0) {
238 y
= top
->left
; /* rotate right */
239 top
->left
= y
->right
;
243 if (top
->left
== NULL
)
247 r
->left
= top
; /* link right */
250 } else if (splayLastResult
> 0) {
251 if (top
->right
== NULL
)
254 if ((splayLastResult
= compare(dataToFind
, top
->right
->data
)) > 0) {
255 y
= top
->right
; /* rotate left */
256 top
->right
= y
->left
;
260 if (top
->right
== NULL
)
264 l
->right
= top
; /* link left */
272 l
->right
= top
->left
; /* assemble */
273 r
->left
= top
->right
;
280 template <class FindValue
>
281 typename Splay
<V
>::Value
const *
282 Splay
<V
>::find (FindValue
const &value
, int( * compare
)(FindValue
const &a
, Value
const &b
)) const
284 head
= head
->splay(value
, compare
);
286 if (splayLastResult
!= 0)
294 Splay
<V
>::insert(Value
const &value
, SPLAYCMP
*compare
)
296 assert (!find (value
, compare
));
297 head
= head
->insert(value
, compare
);
303 Splay
<V
>::remove(Value
const &value
, SPLAYCMP
*compare
)
305 assert (find (value
, compare
));
307 head
= head
->remove(value
, compare
);
314 Splay
<V
>:: start() const
317 return head
->start();
324 Splay
<V
>:: finish() const
327 return head
->finish();
334 Splay
<V
>:: destroy(SPLAYFREE
*free_func
)
337 head
->destroy(free_func
);
346 Splay
<V
>::size() const
352 const SplayConstIterator
<V
>
353 Splay
<V
>::begin() const
355 return const_iterator(head
);
359 const SplayConstIterator
<V
>
360 Splay
<V
>::end() const
362 return const_iterator(NULL
);
366 class SplayConstIterator
370 typedef const V value_type
;
371 SplayConstIterator (SplayNode
<V
> *aNode
);
372 bool operator == (SplayConstIterator
const &right
) const;
373 SplayConstIterator
operator ++ (int dummy
);
374 SplayConstIterator
&operator ++ ();
375 V
const & operator * () const;
379 void addLeftPath(SplayNode
<V
> *aNode
);
380 void init(SplayNode
<V
> *);
381 std::stack
<SplayNode
<V
> *> toVisit
;
385 SplayConstIterator
<V
>::SplayConstIterator (SplayNode
<V
> *aNode
)
392 SplayConstIterator
<V
>::operator == (SplayConstIterator
const &right
) const
394 if (toVisit
.empty() && right
.toVisit
.empty())
396 if (!toVisit
.empty() && !right
.toVisit
.empty())
397 return toVisit
.top() == right
.toVisit
.top();
398 // only one of the two is empty
403 SplayConstIterator
<V
> &
404 SplayConstIterator
<V
>::operator ++ ()
411 SplayConstIterator
<V
>
412 SplayConstIterator
<V
>::operator ++ (int dummy
)
414 SplayConstIterator
<V
> result
= *this;
419 /* advance is simple enough:
420 * if the stack is empty, we're done.
421 * otherwise, pop the last visited node
422 * then, pop the next node to visit
423 * if that has a right child, add it and it's
425 * then add the node back.
429 SplayConstIterator
<V
>::advance()
440 SplayNode
<V
> *currentNode
= toVisit
.top();
443 addLeftPath(currentNode
->right
);
445 toVisit
.push(currentNode
);
450 SplayConstIterator
<V
>::addLeftPath(SplayNode
<V
> *aNode
)
458 } while (aNode
!= NULL
);
463 SplayConstIterator
<V
>::init(SplayNode
<V
> *head
)
470 SplayConstIterator
<V
>::operator * () const
472 /* can't dereference when past the end */
474 if (toVisit
.size() == 0)
475 fatal ("Attempt to dereference SplayConstIterator past-the-end\n");
477 return toVisit
.top()->data
;
480 #endif /* cplusplus */
482 #endif /* SQUID_SPLAY_H */