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

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

Revision 4008, 33.1 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.LinkedList;
18
19 private import  tango.util.container.Slink;
20
21 public  import  tango.util.container.Container;
22
23 private import tango.util.container.model.IContainer;
24
25 /*******************************************************************************
26
27         List of singly-linked values
28
29         ---
30     Iterator iterator ()
31         int opApply (int delegate(ref V value) dg)
32
33         V head ()
34         V tail ()
35         V head (V value)
36         V tail (V value)
37         V removeHead ()
38         V removeTail ()
39
40         bool contains (V value)
41         uint first (V value, uint startingIndex = 0)
42         uint last (V value, uint startingIndex = 0)
43
44         LinkedList add (V value)
45         LinkedList prepend (V value)
46         uint prepend (IContainer!(V) e)
47         LinkedList append (V value)
48         uint append (IContainer!(V) e)
49         LinkedList addAt (uint index, V value)
50         uint addAt (uint index, IContainer!(V) e)
51
52         V get (uint index)
53         bool take (ref V v)
54         uint remove (V value, bool all)
55         bool removeAt (uint index)
56         uint removeRange (uint fromIndex, uint toIndex)
57         uint replace (V oldElement, V newElement, bool all)
58         bool replaceAt (uint index, V value)
59
60         LinkedList clear ()
61         LinkedList reset ()
62
63         LinkedList subset (uint from, uint length = int.max)
64         LinkedList dup ()
65
66         uint size ()
67         bool isEmpty ()
68         V[] toArray (V[] dst)
69         LinkedList sort (Compare!(V) cmp)
70         LinkedList check ()
71         ---
72
73 *******************************************************************************/
74
75 class LinkedList (V, alias Reap = Container.reap,
76                      alias Heap = Container.Collect)
77                      : IContainer!(V)
78 {
79         // use this type for Allocator configuration
80         private alias Slink!(V) Type;
81        
82         private alias Type*     Ref;
83         private alias V*        VRef;
84
85         private alias Heap!(Type) Alloc;
86
87         // number of elements contained
88         private uint            count;
89
90         // configured heap manager
91         private Alloc           heap;
92        
93         // mutation tag updates on each change
94         private uint            mutation;
95
96         // head of the list. Null if empty
97         private Ref             list;
98
99         /***********************************************************************
100
101                 Create a new empty list
102
103         ***********************************************************************/
104
105         this ()
106         {
107                 this (null, 0);
108         }
109
110         /***********************************************************************
111
112                 Special version of constructor needed by dup
113
114         ***********************************************************************/
115
116         protected this (Ref l, int c)
117         {
118                 list = l;
119                 count = c;
120         }
121
122         /***********************************************************************
123
124                 Clean up when deleted
125
126         ***********************************************************************/
127
128         ~this ()
129         {
130                 reset;
131         }
132
133         /***********************************************************************
134
135                 Return the configured allocator
136                 
137         ***********************************************************************/
138
139         final Alloc allocator ()
140         {
141                 return heap;
142         }
143
144         /***********************************************************************
145
146                 Return a generic iterator for contained elements
147                 
148         ***********************************************************************/
149
150         final Iterator iterator ()
151         {
152                 Iterator i = void;
153                 i.mutation = mutation;
154                 i.node = list ? *(i.hook = &list) : null;
155                 i.prior = null;
156                 i.owner = this;
157                 return i;
158         }
159
160         /***********************************************************************
161
162
163         ***********************************************************************/
164
165         final int opApply (int delegate(ref V value) dg)
166         {
167                 return iterator.opApply (dg);
168         }
169
170         /***********************************************************************
171
172                 Return the number of elements contained
173                 
174         ***********************************************************************/
175
176         final uint size ()
177         {
178                 return count;
179         }
180
181         /***********************************************************************
182
183                 Build an independent copy of the list.
184                 The elements themselves are not cloned
185
186         ***********************************************************************/
187
188         final LinkedList dup ()
189         {
190                 return new LinkedList!(V, Reap, Heap) (list ? list.copy(&heap.allocate) : null, count);
191         }
192
193         /***********************************************************************
194
195                 Time complexity: O(n)
196
197         ***********************************************************************/
198
199         final bool contains (V value)
200         {
201                 if (count is 0)
202                     return false;
203
204                 return list.find(value) !is null;
205         }
206
207         /***********************************************************************
208
209                  Time complexity: O(1)
210
211         ***********************************************************************/
212
213         final V head ()
214         {
215                 return firstCell.value;
216         }
217
218         /***********************************************************************
219
220                  Time complexity: O(n)
221
222         ***********************************************************************/
223
224         final V tail ()
225         {
226                 return lastCell.value;
227         }
228
229         /***********************************************************************
230
231                  Time complexity: O(n)
232
233         ***********************************************************************/
234
235         final V get (uint index)
236         {
237                 return cellAt(index).value;
238         }
239
240         /***********************************************************************
241
242                  Time complexity: O(n)
243
244         ***********************************************************************/
245
246         final uint first (V value, uint startingIndex = 0)
247         {
248                 if (list is null || startingIndex >= count)
249                     return uint.max;
250
251                 if (startingIndex < 0)
252                     startingIndex = 0;
253
254                 auto p = list.nth (startingIndex);
255                 if (p)
256                    {
257                    auto i = p.index (value);
258                    if (i >= 0)
259                        return i + startingIndex;
260                    }
261                 return uint.max;
262         }
263
264         /***********************************************************************
265
266                  Time complexity: O(n)
267
268         ***********************************************************************/
269
270         final uint last (V value, uint startingIndex = 0)
271         {
272                 if (list is null)
273                     return uint.max;
274
275                 auto i = 0;
276                 if (startingIndex >= count)
277                     startingIndex = count - 1;
278
279                 auto index = uint.max;
280                 auto p = list;
281                 while (i <= startingIndex && p)
282                       {
283                       if (p.value == value)
284                           index = i;
285                       ++i;
286                       p = p.next;
287                       }
288                 return index;
289         }
290
291         /***********************************************************************
292
293                  Time complexity: O(length)
294
295         ***********************************************************************/
296
297         final LinkedList subset (uint from, uint length = int.max)
298         {
299                 Ref newlist = null;
300
301                 if (length > 0)
302                    {
303                    auto p = cellAt (from);
304                    auto current = newlist = heap.allocate.set (p.value, null);
305          
306                    for (auto i = 1; i < length; ++i)
307                         if ((p = p.next) is null)
308                              length = i;
309                         else
310                            {
311                            current.attach (heap.allocate.set (p.value, null));
312                            current = current.next;
313                            }
314                    }
315
316                 return new LinkedList (newlist, length);
317         }
318
319         /***********************************************************************
320
321                  Time complexity: O(n)
322
323         ***********************************************************************/
324
325         final LinkedList clear ()
326         {
327                 return clear (false);
328         }
329
330         /***********************************************************************
331
332                 Reset the HashMap contents and optionally configure a new
333                 heap manager. We cannot guarantee to clean up reconfigured
334                 allocators, so be sure to invoke reset() before discarding
335                 this class
336
337                 Time complexity: O(n)
338                 
339         ***********************************************************************/
340
341         final LinkedList reset ()
342         {
343                 return clear (true);
344         }
345
346         /***********************************************************************
347         
348                 Takes the first value on the list
349
350                 Time complexity: O(1)
351
352         ***********************************************************************/
353
354         final bool take (ref V v)
355         {
356                 if (count)
357                    {
358                    v = head;
359                    removeHead;
360                    return true;
361                    }
362                 return false;
363         }
364
365         /***********************************************************************
366
367                 Uses a merge-sort-based algorithm.
368
369                 Time complexity: O(n log n)
370
371         ***********************************************************************/
372
373         final LinkedList sort (Compare!(V) cmp)
374         {
375                 if (list)
376                    {
377                    list = Ref.sort (list, cmp);
378                    mutate;
379                    }
380                 return this;
381         }
382
383         /***********************************************************************
384
385                 Time complexity: O(1)
386
387         ***********************************************************************/
388
389         final LinkedList add (V value)
390         {
391                 return prepend (value);
392         }
393
394         /***********************************************************************
395
396                 Time complexity: O(1)
397
398         ***********************************************************************/
399
400         final LinkedList prepend (V value)
401         {
402                 list = heap.allocate.set (value, list);
403                 increment;
404                 return this;
405         }
406
407         /***********************************************************************
408
409                 Time complexity: O(n)
410
411         ***********************************************************************/
412
413         final uint remove (V value, bool all = false)
414         {
415                 auto c = count;
416                 if (c)
417                    {
418                    auto p = list;
419                    auto trail = p;
420
421                    while (p)
422                          {
423                          auto n = p.next;
424                          if (p.value == value)
425                             {
426                             decrement (p);
427                             if (p is list)
428                                {
429                                list = n;
430                                trail = n;
431                                }
432                             else
433                                trail.next = n;
434
435                             if (!all || count is 0)
436                                  break;
437                             else
438                                p = n;
439                             }
440                          else
441                             {
442                             trail = p;
443                             p = n;
444                             }
445                          }
446                    }
447                 return c - count;
448         }
449
450         /***********************************************************************
451
452                 Time complexity: O(n)
453
454         ***********************************************************************/
455
456         final uint replace (V oldElement, V newElement, bool all = false)
457         {
458                 uint c;
459                 if (count && oldElement != newElement)
460                    {
461                    auto p = list.find (oldElement);
462                    while (p)
463                          {
464                          ++c;
465                          mutate;
466                          p.value = newElement;
467                          if (!all)
468                               break;
469                          p = p.find (oldElement);
470                          }
471                    }
472                 return c;
473         }
474
475         /***********************************************************************
476
477                  Time complexity: O(1)
478
479         ***********************************************************************/
480
481         final V head (V value)
482         {
483                 auto cell = firstCell;
484                 auto v = cell.value;
485                 cell.value = value;
486                 mutate;
487                 return v;
488         }
489
490         /***********************************************************************
491
492                  Time complexity: O(1)
493
494         ***********************************************************************/
495
496         final V removeHead ()
497         {
498                 auto p = firstCell;
499                 auto v = p.value;
500                 list = p.next;
501                 decrement (p);
502                 return v;
503         }
504
505         /***********************************************************************
506
507                  Time complexity: O(n)
508
509         ***********************************************************************/
510
511         final LinkedList append (V value)
512         {
513                 if (list is null)
514                     prepend (value);
515                 else
516                    {
517                    list.tail.next = heap.allocate.set (value, null);
518                    increment;
519                    }
520                 return this;
521         }
522
523         /***********************************************************************
524
525                  Time complexity: O(n)
526
527         ***********************************************************************/
528
529         final V tail (V value)
530         {
531                 auto p = lastCell;
532                 auto v = p.value;
533                 p.value = value;
534                 mutate;
535                 return v;
536         }
537
538         /***********************************************************************
539
540                  Time complexity: O(n)
541
542         ***********************************************************************/
543
544         final V removeTail ()
545         {
546                 if (firstCell.next is null)
547                     return removeHead;
548
549                 auto trail = list;
550                 auto p = trail.next;
551
552                 while (p.next)
553                       {
554                       trail = p;
555                       p = p.next;
556                       }
557                 trail.next = null;
558                 auto v = p.value;
559                 decrement (p);
560                 return v;
561         }
562
563         /***********************************************************************
564
565                 Time complexity: O(n)
566
567         ***********************************************************************/
568
569         final LinkedList addAt (uint index, V value)
570         {
571                 if (index is 0)
572                     prepend (value);
573                 else
574                    {
575                    cellAt(index - 1).attach (heap.allocate.set(value, null));
576                    increment;
577                    }
578                 return this;
579         }
580
581         /***********************************************************************
582
583                  Time complexity: O(n)
584
585         ***********************************************************************/
586
587         final LinkedList removeAt (uint index)
588         {
589                 if (index is 0)
590                     removeHead;
591                 else
592                    {
593                    auto p = cellAt (index - 1);
594                    auto t = p.next;
595                    p.detachNext;
596                    decrement (t);
597                    }
598                 return this;
599         }
600
601         /***********************************************************************
602
603                  Time complexity: O(n)
604
605         ***********************************************************************/
606
607         final LinkedList replaceAt (uint index, V value)
608         {
609                 cellAt(index).value = value;
610                 mutate;
611                 return this;
612         }
613
614         /***********************************************************************
615
616                  Time complexity: O(number of elements in e)
617
618         ***********************************************************************/
619
620         final uint prepend (IContainer!(V) e)
621         {
622                 auto c = count;
623                 splice_ (e, null, list);
624                 return count - c;
625         }
626
627         /***********************************************************************
628
629                  Time complexity: O(n + number of elements in e)
630
631         ***********************************************************************/
632
633         final uint append (IContainer!(V) e)
634         {
635                 auto c = count;
636                 if (list is null)
637                     splice_ (e, null, null);
638                 else
639                    splice_ (e, list.tail, null);
640                 return count - c;
641         }
642
643         /***********************************************************************
644
645                 Time complexity: O(n + number of elements in e)
646
647         ***********************************************************************/
648
649         final uint addAt (uint index, IContainer!(V) e)
650         {
651                 auto c = count;
652                 if (index is 0)
653                     splice_ (e, null, list);
654                 else
655                    {
656                    auto p = cellAt (index - 1);
657                    splice_ (e, p, p.next);
658                    }
659                 return count - c;
660         }
661
662         /***********************************************************************
663
664                 Time complexity: O(n)
665
666         ***********************************************************************/
667
668         final uint removeRange (uint fromIndex, uint toIndex)
669         {
670                 auto c = count;
671                 if (fromIndex <= toIndex)
672                    {
673                    if (fromIndex is 0)
674                       {
675                       auto p = firstCell;
676                       for (int i = fromIndex; i <= toIndex; ++i)
677                            p = p.next;
678                       list = p;
679                       }
680                    else
681                       {
682                       auto f = cellAt (fromIndex - 1);
683                       auto p = f;
684                       for (int i = fromIndex; i <= toIndex; ++i)
685                            p = p.next;
686                       f.next = p.next;
687                       }
688
689                   count -= (toIndex - fromIndex + 1);
690                   mutate;
691                   }
692                 return c - count;
693         }
694
695         /***********************************************************************
696
697                 Copy and return the contained set of values in an array,
698                 using the optional dst as a recipient (which is resized
699                 as necessary).
700
701                 Returns a slice of dst representing the container values.
702                 
703                 Time complexity: O(n)
704                 
705         ***********************************************************************/
706
707         final V[] toArray (V[] dst = null)
708         {
709                 if (dst.length < count)
710                     dst.length = count;
711
712                 int i = 0;
713 &nbs