Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

root/trunk/tango/util/container/Slink.d

Revision 4008, 15.5 kB (checked in by larsivi, 1 month ago)

Fixed eol style for container package, refs #1303

  • Property svn:eol-style set to native
Line 
1 /*******************************************************************************
2
3         copyright:      Copyright (c) 2008 Kris Bell. All rights reserved
4
5         license:        BSD style: $(LICENSE)
6
7         version:        Apr 2008: Initial release
8
9         authors:        Kris
10
11         Since:          0.99.7
12
13         Based upon Doug Lea's Java collection package
14
15 *******************************************************************************/
16
17 module tango.util.container.Slink;
18
19 private import tango.util.container.model.IContainer;
20
21 /*******************************************************************************
22
23         Slink instances provide standard linked list next-fields, and
24         support standard operations upon them. Slink structures are pure
25         implementation tools, and perform no argument checking, no result
26         screening, and no synchronization. They rely on user-level classes
27         (see HashSet, for example) to do such things.
28
29         Still, Slink is made `public' so that you can use it to build other
30         kinds of containers
31         
32         Note that when K is specified, support for keys are enabled. When
33         Identity is stipulated as 'true', those keys are compared using an
34         identity-comparison instead of equality (using 'is').
35
36 *******************************************************************************/
37
38 private typedef int KeyDummy;
39
40 struct Slink (V, K=KeyDummy, bool Identity = false)
41 {
42         alias Slink!(V, K)      Type;
43         alias Type              *Ref;
44         alias Compare!(V)       Comparator;
45
46
47         Ref     next;           // pointer to next
48         V       value;          // element value
49                
50         /***********************************************************************
51
52                 add support for keys also?
53                 
54         ***********************************************************************/
55
56         static if (!is(typeof(K) == KeyDummy))
57         {
58                 K key;
59
60                 final Ref set (K k, V v, Ref n)
61                 {
62                         key = k;
63                         return set (v, n);
64                 }
65
66                 final int hash()
67                 {
68                         return typeid(K).getHash(&key);
69                 }
70
71                 final Ref findKey (K key)
72                 {
73                         static if (Identity == true)
74                         {
75                            for (auto p=this; p; p = p.next)
76                                 if (key is p.key)
77                                     return p;
78                         }
79                         else
80                         {
81                            for (auto p=this; p; p = p.next)
82                                 if (key == p.key)
83                                     return p;
84                         }
85                         return null;
86                 }
87
88                 final Ref findPair (K key, V value)
89                 {
90                         static if (Identity == true)
91                         {
92                            for (auto p=this; p; p = p.next)
93                                 if (key is p.key && value == p.value)
94                                     return p;
95                         }
96                         else
97                         {
98                            for (auto p=this; p; p = p.next)
99                                 if (key == p.key && value == p.value)
100                                     return p;
101                         }
102                         return null;
103                 }
104
105                 final int indexKey (K key)
106                 {
107                         int i = 0;
108                         static if (Identity == true)
109                         {
110                            for (auto p=this; p; p = p.next, ++i)
111                                 if (key is p.key)
112                                     return i;
113                         }
114                         else
115                         {
116                            for (auto p=this; p; p = p.next, ++i)
117                                 if (key == p.key)
118                                     return i;
119                         }
120                         return -1;
121                 }
122
123                 final int indexPair (K key, V value)
124                 {
125                         int i = 0;
126                         static if (Identity == true)
127                         {
128                            for (auto p=this; p; p = p.next, ++i)
129                                 if (key is p.key && value == p.value)
130                                     return i;
131                         }
132                         else
133                         {
134                            for (auto p=this; p; p = p.next, ++i)
135                                 if (key == p.key && value == p.value)
136                                     return i;
137                         }
138                         return -1;
139                 }
140
141                 final int countKey (K key)
142                 {
143                         int c = 0;
144                         static if (Identity == true)
145                         {
146                            for (auto p=this; p; p = p.next)
147                                 if (key is p.key)
148                                     ++c;
149                         }
150                         else
151                         {
152                            for (auto p=this; p; p = p.next)
153                                 if (key == p.key)
154                                     ++c;
155                         }
156                         return c;
157                 }
158
159                 final int countPair (K key, V value)
160                 {
161                         int c = 0;
162                         static if (Identity == true)
163                         {
164                            for (auto p=this; p; p = p.next)
165                                 if (key is p.key && value == p.value)
166                                     ++c;
167                         }
168                         else
169                         {
170                            for (auto p=this; p; p = p.next)
171                                 if (key == p.key && value == p.value)
172                                     ++c;
173                         }
174                         return c;
175                 }
176         }
177        
178         /***********************************************************************
179
180                  Set to point to n as next cell
181
182                  param: n, the new next cell
183                         
184         ***********************************************************************/
185
186         final Ref set (V v, Ref n)
187         {
188                 next = n;
189                 value = v;
190                 return this;
191         }
192
193         /***********************************************************************
194
195                  Splice in p between current cell and whatever it was
196                  previously pointing to
197
198                  param: p, the cell to splice
199                         
200         ***********************************************************************/
201
202         final void attach (Ref p)
203         {
204                 if (p)
205                     p.next = next;
206                 next = p;
207         }
208
209         /***********************************************************************
210
211                 Cause current cell to skip over the current next() one,
212                 effectively removing the next element from the list
213                         
214         ***********************************************************************/
215
216         final void detachNext()
217         {
218                 if (next)
219                     next = next.next;
220         }
221
222         /***********************************************************************
223
224                  Linear search down the list looking for element
225                 
226                  param: element to look for
227                  Returns: the cell containing element, or null if no such
228                 
229         ***********************************************************************/
230
231         final Ref find (V element)
232         {
233                 for (auto p = this; p; p = p.next)
234                      if (element == p.value)
235                          return p;
236                 return null;
237         }
238
239         /***********************************************************************
240
241                 Return the number of cells traversed to find first occurrence
242                 of a cell with element() element, or -1 if not present
243                         
244         ***********************************************************************/
245
246         final int index (V element)
247         {
248                 int i;
249                 for (auto p = this; p; p = p.next, ++i)
250                      if (element == p.value)
251                          return i;
252
253                 return -1;
254         }
255
256         /***********************************************************************
257
258                 Count the number of occurrences of element in list
259                         
260         ***********************************************************************/
261
262         final int count (V element)
263         {
264                 int c;
265                 for (auto p = this; p; p = p.next)
266                      if (element == p.value)
267                          ++c;
268                 return c;
269         }
270
271         /***********************************************************************
272
273                  Return the number of cells in the list
274                         
275         ***********************************************************************/
276
277         final int count ()
278         {
279                 int c;
280                 for (auto p = this; p; p = p.next)
281                      ++c;
282                 return c;
283         }
284
285         /***********************************************************************
286
287                 Return the cell representing the last element of the list
288                 (i.e., the one whose next() is null
289                         
290         ***********************************************************************/
291
292         final Ref tail ()
293         {
294                 auto p = this;
295                 while (p.next)
296                        p = p.next;
297                 return p;
298         }
299
300         /***********************************************************************
301
302                 Return the nth cell of the list, or null if no such
303                         
304         ***********************************************************************/
305
306         final Ref nth (int n)
307         {
308                 auto p = this;
309                 for (int i; i < n; ++i)
310                      p = p.next;
311                 return p;
312         }
313
314         /***********************************************************************
315
316                 Make a copy of the list; i.e., a new list containing new cells
317                 but including the same elements in the same order
318                         
319         ***********************************************************************/
320
321         final Ref copy (Ref delegate() alloc)
322         {
323                 auto newlist = dup (alloc);
324                 auto current = newlist;
325
326                 for (auto p = next; p; p = p.next)
327                     {
328                     current.next = p.dup (alloc);
329                     current = current.next;
330                     }
331                 current.next = null;
332                 return newlist;
333         }
334
335         /***********************************************************************
336
337                 dup is shallow; i.e., just makes a copy of the current cell
338                         
339         ***********************************************************************/
340
341         private Ref dup (Ref delegate() alloc)
342         {
343                 auto ret = alloc();
344                 static if (is(typeof(K) == KeyDummy))
345                            ret.set (value, next);
346                        else
347                           ret.set (key, value, next);
348                 return ret;
349         }
350
351         /***********************************************************************
352
353                 Basic linkedlist merge algorithm.
354                 Merges the lists head by fst and snd with respect to cmp
355         
356                 param: fst head of the first list
357                 param: snd head of the second list
358                 param: cmp a Comparator used to compare elements
359                 Returns: the merged ordered list
360                         
361         ***********************************************************************/
362
363         static Ref merge (Ref fst, Ref snd, Comparator cmp)
364         {
365                 auto a = fst;
366                 auto b = snd;
367                 Ref hd = null;
368                 Ref current = null;
369
370                 for (;;)
371                     {
372                     if (a is null)
373                        {
374                        if (hd is null)
375                            hd = b;
376                        else
377                           current.next = b;
378                        return hd;
379                        }
380                     else
381                        if (b is null)
382                           {
383                           if (hd is null)
384                               hd = a;
385                           else
386                              current.next = a;
387                           return hd;
388                           }
389
390                     int diff = cmp (a.value, b.value);
391                     if (diff <= 0)
392                        {
393                        if (hd is null)
394                            hd = a;
395                        else
396                           current.next = a;
397                        current = a;
398                        a = a.next;
399                        }
400                     else
401                        {
402                        if (hd is null)
403                            hd = b;
404                        else
405                           current.next = b;
406                        current = b;
407                        b = b.next;
408                        }
409                     }
410                 return null;
411         }
412
413         /***********************************************************************
414
415                 Standard list splitter, used by sort.
416                 Splits the list in half. Returns the head of the second half
417
418                 param: s the head of the list
419                 Returns: the head of the second half
420
421         ***********************************************************************/
422
423         static Ref split (Ref s)
424         {
425                 auto fast = s;
426                 auto slow = s;
427
428                 if (fast is null || fast.next is null)
429                     return null;
430
431                 while (fast)
432                       {
433                       fast = fast.next;
434                       if (fast && fast.next)
435                          {
436                          fast = fast.next;
437                          slow = slow.next;
438                          }
439                       }
440
441                 auto r = slow.next;
442                 slow.next = null;
443                 return r;
444
445         }
446
447         /***********************************************************************
448
449                  Standard merge sort algorithm
450                 
451                  param: s the list to sort
452                  param: cmp, the comparator to use for ordering
453                  Returns: the head of the sorted list
454                         
455         ***********************************************************************/
456
457         static Ref sort (Ref s, Comparator cmp)
458         {
459                 if (s is null || s.next is null)
460                     return s;
461                 else
462                    {
463                    auto right = split (s);
464                    auto left = s;
465                    left = sort (left, cmp);
466                    right = sort (right, cmp);
467                    return merge (left, right, cmp);
468                    }
469         }
470
471 }
Note: See TracBrowser for help on using the browser.