source: liacs/da/opdr2b/trie.cc@ 324

Last change on this file since 324 was 2, checked in by Rick van der Zwet, 15 years ago

Initial import of data of old repository ('data') worth keeping (e.g. tracking
means of URL access statistics)

File size: 8.6 KB
Line 
1/* Author : Rick van der Zwet
2 * S-number : 0433373
3 * Version : $Id: trie.cc 330 2007-11-25 23:31:30Z rick $
4 * Copyright : FreeBSD Licence
5 */
6
7#include "trie.h"
8#include <stdlib.h>
9#include <stdio.h>
10
11#ifndef TRIE_CC
12#define TRIE_CC
13
14template <class InfoTp>
15TrieNode<InfoTp>::TrieNode()
16{
17 Value = '\0';
18 One = NULL;
19 Zero = NULL;
20 Parent = NULL;
21}
22
23
24
25template <class InfoTp>
26TrieNode<InfoTp>::~TrieNode()
27{
28 delete One;
29 delete Zero;
30}
31
32
33
34template <class InfoTp>
35Trie<InfoTp>::Trie ()
36{
37 Root = new TrieNode<InfoTp> ();
38 //Set window to root
39 GoRoot ();
40}
41
42
43
44template <class InfoTp>
45Trie<InfoTp>::~Trie ()
46{
47 delete Root;
48}
49
50
51
52template <class InfoTp>
53bool Trie<InfoTp>::AtLeaf ()
54{
55 if (Window->One == NULL and Window->Zero == NULL)
56 {
57 return(true);
58 }
59
60 // Got some extra nodes down below
61 return(false);
62}
63
64
65
66template <class InfoTp>
67void Trie<InfoTp>::GoChild (char K)
68{
69 // Call ExistsChild to check if node exists and deliver an pointer
70 // to the node in NodeFound
71 if ( ExistsChild(K) )
72 {
73 Window = NodeFound;
74 }
75}
76
77
78
79template <class InfoTp>
80void Trie<InfoTp>::GoRoot ()
81{
82 //set the current window on the Root pointer
83 Window = Root;
84}
85
86
87
88template <class InfoTp>
89bool Trie<InfoTp>::ExistsChild (char K)
90{
91 // worker with different knob, to make it able to get back
92 TrieNode<InfoTp> * Worker = Window;
93
94 int i;
95 for (i = 7; i >= 0; i--)
96 {
97 // bit i is 1 or not?
98 if (K & 1<<i)
99 {
100 // If node not exists, bail out
101 if (Worker->One == NULL)
102 {
103 return false;
104 }
105 else
106 {
107 Worker = Worker->One;
108 }
109 }
110 else
111 {
112 // If node not exists, bail out
113 if (Worker->Zero == NULL)
114 {
115 return false;
116 }
117 else
118 {
119 Worker = Worker->Zero;
120 }
121 }
122 }
123
124 // Store found window in NodeFound
125 NodeFound = Worker;
126 return true;
127}
128
129
130
131template <class InfoTp>
132char Trie<InfoTp>::FirstChild ()
133{
134 // worker with different knob, to make it able to get back
135 TrieNode<InfoTp> * Worker = Window;
136 // walk 8 bits, i indication of the bit currently are
137 int i;
138 // return value
139 char retval = 0;
140 for (i = 7; i >= 0; i--)
141 {
142 // go as many Zero if possible else go right if possible else return \0
143 if (Worker->Zero != NULL)
144 {
145 Worker = Worker->Zero;
146 }
147 else if (Worker->One != NULL)
148 {
149 //set bit i to 1
150 retval |= 1<<i;
151 Worker = Worker->One;
152 }
153 else
154 {
155 retval = '\0';
156 break;
157 }
158 }
159 return(retval);
160}
161
162
163
164/* This does not seems be very logical in the first place, but try to
165 * draw a picture and then follow the paths, just remind 2 things
166 * -no One 'turns' are allowed, cause those are higher order childs
167 * -the story ends if you hit the startnode from the right
168 * XXX: Only works well with one level depth, not multilevel depth
169 */
170template <class InfoTp>
171char Trie<InfoTp>::NextChild (char K)
172{
173 // store startnode
174 TrieNode<InfoTp> * Worker;
175 // tmp (loop) counter
176 int i;
177 // return value, not changed if not found
178 int retval = '\0';
179
180 // goto child node if it exists at least
181 if (ExistsChild(K)) {
182 Worker = NodeFound;
183
184 // depth counter
185 i = 0;
186 while ( true )
187 {
188 // ends if in startnode and came from right or
189 // in startnode en no left turn possible
190 if (Worker->Parent == Window)
191 {
192 if (Worker->Parent->One == Worker or
193 Worker->Parent->One == NULL)
194 {
195 return(retval);
196 }
197 }
198
199 //if from left and right available, go for it
200 if (Worker->Parent->Zero == Worker and
201 Worker->Parent->One != NULL)
202 {
203 Worker = Worker->Parent->One;
204
205 //walk to child leaf
206 while (i > 0)
207 {
208 //decrement counter, cause we are going inward again
209 i--;
210 // if left available take it, else right
211 if (Worker->Zero != NULL)
212 {
213 Worker = Worker->Zero;
214 }
215 else
216 {
217 Worker = Worker->One;
218 }
219 }
220
221 //calculate value NextChild
222 retval = 0;
223 for (i = 0; i <= 7; i++)
224 {
225 if (Worker->Parent->One == Worker)
226 {
227 retval |= 1<<i;
228 }
229 Worker = Worker->Parent;
230 }
231
232 //should never happen
233 if (Worker != Window)
234 {
235 perror("BUG: NextChild find value error");
236 exit(1);
237 }
238 return(retval);
239 }
240
241 //set new value Worker
242 Worker = Worker->Parent;
243 //raise counter
244 i++;
245 }
246 // end none found
247 return(retval);
248 }
249 // no valid leaf
250 return(retval);
251}
252
253
254
255template <class InfoTp>
256void Trie<InfoTp>::AddChild (char K)
257{
258 //get worker pointer
259 TrieNode<InfoTp> * Worker = Window;
260
261 int i;
262 for (i = 7; i >= 0; i--)
263 {
264 //bit i is 1 or not?
265 if (K & 1<<i)
266 {
267 // check is node exists, else create new one
268 if (Worker->One == NULL)
269 {
270 Worker->One = new TrieNode<InfoTp>();
271 }
272 Worker->One->Parent = Worker;
273 Worker = Worker->One;
274 }
275 else {
276 // check is node exists, else create new one
277 if (Worker->Zero == NULL)
278 {
279 Worker->Zero = new TrieNode<InfoTp>();
280 }
281 Worker->Zero->Parent = Worker;
282 Worker = Worker->Zero;
283 }
284 }
285}
286
287
288
289template <class InfoTp>
290void Trie<InfoTp>::RemoveChild (char K)
291{
292 TrieNode<InfoTp> * Worker;
293 int i; //loop counter
294 //check whether this knob exists
295 if ( ExistsChild(K) )
296 {
297 Worker = NodeFound;
298 //and is leaf
299 if (Worker->One == NULL and Worker->Zero == NULL)
300 {
301 //delete obsolete knob and null refering pointer
302 // walk 7 steps up and delete node if both pointers are zero
303 // first step is special cause the other could be a leaf as
304 // well
305
306
307 //goto parent
308 Worker = Worker->Parent;
309 //deleted leaf specified at NodeFound
310 if (Worker->One == NodeFound)
311 {
312 delete Worker->One;
313 Worker->One = NULL;
314 }
315 else
316 {
317 delete Worker->Zero;
318 Worker->Zero = NULL;
319 }
320
321 for (i = 0; i <= 6; i++)
322 {
323 // go one up
324 Worker = Worker->Parent;
325
326 //XXX: Only need to check the node we came from, instead
327 //of both
328
329 // Check wether we could delete arch 1
330 if (Worker->One != NULL)
331 {
332 //delete subnode if both pointers are NULL
333 if (Worker->One->One == NULL and
334 Worker->One->Zero == NULL)
335 {
336 delete Worker->One;
337 Worker->One = NULL;
338 }
339 }
340
341 // Check wether we could delete arch 0
342 if (Worker->Zero != NULL)
343 {
344 //delete subnode if both pointers are NULL
345 if (Worker->Zero->One == NULL and
346 Worker->Zero->Zero == NULL)
347 {
348 delete Worker->Zero;
349 Worker->Zero = NULL;
350 }
351 }
352 }
353
354 //Should never happen
355 if (Window != Worker)
356 {
357 perror("BUG: Pointer delete error");
358 exit(1);
359 }
360 }
361 }
362}
363
364
365
366template <class InfoTp>
367void Trie<InfoTp>::PutInfo (InfoTp I)
368{
369 Window->Value = I;
370}
371
372
373
374template <class InfoTp>
375InfoTp Trie<InfoTp>::GetInfo ()
376{
377 return(Window->Value);
378}
379
380
381
382template <class InfoTp>
383void Trie<InfoTp>::GotoNode(TrieNode<InfoTp> *Nd)
384{
385 Window = Nd;
386}
387
388
389
390template <class InfoTp>
391TrieNode<InfoTp> *Trie<InfoTp>::GetNode()
392{
393 return(Window);
394}
395
396#endif
Note: See TracBrowser for help on using the repository browser.