1 /*
2  * Hunt - A refined core library for D programming language.
3  *
4  * Copyright (C) 2018-2019 HuntLabs
5  *
6  * Website: https://www.huntlabs.net/
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 
12 module hunt.collection.LinkedList;
13 
14 import hunt.collection.AbstractList;
15 import hunt.collection.AbstractSequentialList;
16 import hunt.collection.Collection;
17 import hunt.collection.Deque;
18 import hunt.collection.List;
19 
20 import hunt.Exceptions;
21 import hunt.Object;
22 
23 import std.conv;
24 import std.container;
25 import std.range;
26 
27 
28 
29 /**
30  * Doubly-linked list implementation of the {@code List} and {@code Deque}
31  * interfaces.  Implements all optional list operations, and permits all
32  * elements (including {@code null}).
33  *
34  * <p>All of the operations perform as could be expected for a doubly-linked
35  * list.  Operations that index into the list will traverse the list from
36  * the beginning or the end, whichever is closer to the specified index.
37  *
38  * <p><strong>Note that this implementation is not synchronized.</strong>
39  * If multiple threads access a linked list concurrently, and at least
40  * one of the threads modifies the list structurally, it <i>must</i> be
41  * synchronized externally.  (A structural modification is any operation
42  * that adds or deletes one or more elements; merely setting the value of
43  * an element is not a structural modification.)  This is typically
44  * accomplished by synchronizing on some object that naturally
45  * encapsulates the list.
46  *
47  * If no such object exists, the list should be "wrapped" using the
48  * {@link Collections#synchronizedList Collections.synchronizedList}
49  * method.  This is best done at creation time, to prevent accidental
50  * unsynchronized access to the list:<pre>
51  *   List list = Collections.synchronizedList(new LinkedList(...));</pre>
52  *
53  * <p>The iterators returned by this class's {@code iterator} and
54  * {@code listIterator} methods are <i>fail-fast</i>: if the list is
55  * structurally modified at any time after the iterator is created, in
56  * any way except through the Iterator's own {@code remove} or
57  * {@code add} methods, the iterator will throw a {@link
58  * ConcurrentModificationException}.  Thus, in the face of concurrent
59  * modification, the iterator fails quickly and cleanly, rather than
60  * risking arbitrary, non-deterministic behavior at an undetermined
61  * time in the future.
62  *
63  * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
64  * as it is, generally speaking, impossible to make any hard guarantees in the
65  * presence of unsynchronized concurrent modification.  Fail-fast iterators
66  * throw {@code ConcurrentModificationException} on a best-effort basis.
67  * Therefore, it would be wrong to write a program that depended on this
68  * exception for its correctness:   <i>the fail-fast behavior of iterators
69  * should be used only to detect bugs.</i>
70  *
71  * <p>This class is a member of the
72  * <a href="{@docRoot}/../technotes/guides/collections/index.html">
73  * Java Collections Framework</a>.
74  *
75  * @author  Josh Bloch
76  * @see     List
77  * @see     ArrayList
78  * @since 1.2
79  * @param !E the type of elements held in this collection
80  */
81 
82 class LinkedList(E) : AbstractSequentialList!E,  Deque!E {  //, Cloneable 
83     // alias remove = AbstractSequentialList!E.remove;
84 
85     DList!E _dlist;
86     int _size = 0;
87 
88     /**
89      * Constructs an empty list.
90      */
91     this() {
92     }
93 
94     /**
95      * Constructs a list containing the elements of the specified
96      * collection, in the order they are returned by the collection's
97      * iterator.
98      *
99      * @param  c the collection whose elements are to be placed into this list
100      * @throws NullPointerException if the specified collection is null
101      */
102     this(Collection!E c) {
103         this();
104         addAll(c);
105     }
106 
107 
108     this(E[] c) {
109         this();
110         addAll(c);
111     }
112 
113     /**
114      * Links e as first element.
115      */
116     private void linkFirst(E e) {
117         _dlist.insertFront(e);
118         _size++;
119         modCount++;
120     }
121 
122     /**
123      * Links e as last element.
124      */
125     void linkLast(E e) {
126         _dlist.insertBack(e);
127         _size++;
128         modCount++;
129     }
130 
131     /**
132      * Inserts element e before non-null Node succ.
133      */
134     // void linkBefore(E e, Node!E succ) {
135     //     // assert succ !is null;
136     //     final Node!E pred = succ.prev;
137     //     final Node!E newNode = new Node<>(pred, e, succ);
138     //     succ.prev = newNode;
139     //     if (pred is null)
140     //         first = newNode;
141     //     else
142     //         pred.next = newNode;
143     //     _size++;
144     //     modCount++;
145     // }
146 
147     /**
148      * Unlinks non-null first node f.
149      */
150     private E unlinkFirst() {
151         E element = _dlist.front;
152         _dlist.removeFront();
153         _size--;
154         modCount++;
155         return element;
156     }
157 
158     /**
159      * Unlinks non-null last node l.
160      */
161     private E unlinkLast() {
162         E element = _dlist.back;
163         _dlist.removeBack;
164         _size--;
165         modCount++;
166         return element;
167     }
168 
169 
170     /**
171      * Returns the first element in this list.
172      *
173      * @return the first element in this list
174      * @throws NoSuchElementException if this list is empty
175      */
176     E getFirst() {
177         return _dlist.front;
178     }
179 
180     /**
181      * Returns the last element in this list.
182      *
183      * @return the last element in this list
184      * @throws NoSuchElementException if this list is empty
185      */
186     E getLast() {
187         return _dlist.back;
188     }
189 
190     /**
191      * Removes and returns the first element from this list.
192      *
193      * @return the first element from this list
194      * @throws NoSuchElementException if this list is empty
195      */
196     E removeFirst() {
197         if(_size<=0)  return E.init;
198         return unlinkFirst();
199     }
200 
201     /**
202      * Removes and returns the last element from this list.
203      *
204      * @return the last element from this list
205      * @throws NoSuchElementException if this list is empty
206      */
207     E removeLast() {
208         if(_size<=0) return E.init;
209         return unlinkLast();
210     }
211 
212     /**
213      * Inserts the specified element at the beginning of this list.
214      *
215      * @param e the element to add
216      */
217     void addFirst(E e) {
218         linkFirst(e);
219     }
220 
221     /**
222      * Appends the specified element to the end of this list.
223      *
224      * <p>This method is equivalent to {@link #add}.
225      *
226      * @param e the element to add
227      */
228     void addLast(E e) {
229         linkLast(e);
230     }
231 
232     /**
233      * Returns {@code true} if this list contains the specified element.
234      * More formally, returns {@code true} if and only if this list contains
235      * at least one element {@code e} such that
236      * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
237      *
238      * @param o element whose presence in this list is to be tested
239      * @return {@code true} if this list contains the specified element
240      */
241     override bool contains(E o) {
242         return indexOf(o) != -1;
243     }
244 
245     /**
246      * Returns the number of elements in this list.
247      *
248      * @return the number of elements in this list
249      */
250     override int size() {
251         return _size;
252     }
253 
254     /**
255      * Appends the specified element to the end of this list.
256      *
257      * <p>This method is equivalent to {@link #addLast}.
258      *
259      * @param e element to be appended to this list
260      * @return {@code true} (as specified by {@link Collection#add})
261      */
262     override bool add(E e) {
263         linkLast(e);
264         return true;
265     }
266 
267     /**
268      * Removes the first occurrence of the specified element from this list,
269      * if it is present.  If this list does not contain the element, it is
270      * unchanged.  More formally, removes the element with the lowest index
271      * {@code i} such that
272      * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
273      * (if such an element exists).  Returns {@code true} if this list
274      * contained the specified element (or equivalently, if this list
275      * changed as a result of the call).
276      *
277      * @param o element to be removed from this list, if present
278      * @return {@code true} if this list contained the specified element
279      */
280     override bool remove(E o) {
281         _size--;
282         modCount++;
283         import hunt.util.Common;
284 static if(CompilerHelper.isLessThan(2077)) {
285         auto range = _dlist[];
286         for ( ; !range.empty; range.popFront())
287         {
288             if (range.front == o)
289             {
290                 _dlist.stableLinearRemove(take(range, 1));
291                 return true;
292             }
293         }
294         return false;
295 } else {
296         return _dlist.linearRemoveElement(o);
297 }
298     }
299 
300     // /**
301     //  * Appends all of the elements in the specified collection to the end of
302     //  * this list, in the order that they are returned by the specified
303     //  * collection's iterator.  The behavior of this operation is undefined if
304     //  * the specified collection is modified while the operation is in
305     //  * progress.  (Note that this will occur if the specified collection is
306     //  * this list, and it's nonempty.)
307     //  *
308     //  * @param c collection containing elements to be added to this list
309     //  * @return {@code true} if this list changed as a result of the call
310     //  * @throws NullPointerException if the specified collection is null
311     //  */
312     // override bool addAll(Collection!E c) {
313 
314     //     bool modified = c.size() > 0;
315     //     foreach (E e ; c) {
316     //         linkLast(e);
317     //     }
318     //     return modified;
319 
320     //     // return addAll(_size, c);
321     // }
322 
323     // bool addAll(E[] c) {
324 
325     //     bool modified = c.length > 0;
326     //     foreach (E e ; c) {
327     //         linkLast(e);
328     //     }
329     //     return modified;
330     // }
331 
332 //     /**
333 //      * Inserts all of the elements in the specified collection into this
334 //      * list, starting at the specified position.  Shifts the element
335 //      * currently at that position (if any) and any subsequent elements to
336 //      * the right (increases their indices).  The new elements will appear
337 //      * in the list in the order that they are returned by the
338 //      * specified collection's iterator.
339 //      *
340 //      * @param index index at which to insert the first element
341 //      *              from the specified collection
342 //      * @param c collection containing elements to be added to this list
343 //      * @return {@code true} if this list changed as a result of the call
344 //      * @throws IndexOutOfBoundsException {@inheritDoc}
345 //      * @throws NullPointerException if the specified collection is null
346 //      */
347 
348 // bool addAll(int index, Collection!E c) {
349 //     throw new NotImplementedException();
350 // }
351 //     bool addAll(int index, Collection<E> c) {
352 //         checkPositionIndex(index);
353 
354 //         Object[] a = c.toArray();
355 //         int numNew = a.length;
356 //         if (numNew == 0)
357 //             return false;
358 
359 //         Node!E pred, succ;
360 //         if (index == _size) {
361 //             succ = null;
362 //             pred = last;
363 //         } else {
364 //             succ = node(index);
365 //             pred = succ.prev;
366 //         }
367 
368 //         for (Object o : a) {
369 //         E e = (E) o;
370 //             Node!E newNode = new Node<>(pred, e, null);
371 //             if (pred is null)
372 //                 first = newNode;
373 //             else
374 //                 pred.next = newNode;
375 //             pred = newNode;
376 //         }
377 
378 //         if (succ is null) {
379 //             last = pred;
380 //         } else {
381 //             pred.next = succ;
382 //             succ.prev = pred;
383 //         }
384 
385 //         _size += numNew;
386 //         modCount++;
387 //         return true;
388 //     }
389 
390     /**
391      * Removes all of the elements from this list.
392      * The list will be empty after this call returns.
393      */
394     override void clear() {
395         _dlist.clear();
396         _size = 0;
397         modCount++;
398     }
399 
400 
401     // Positional Access Operations
402 
403     /**
404      * Returns the element at the specified position in this list.
405      *
406      * @param index index of the element to return
407      * @return the element at the specified position in this list
408      * @throws IndexOutOfBoundsException {@inheritDoc}
409      */
410     override E get(int index) {
411         checkElementIndex(index);
412 
413         int i=0;
414         foreach(v; _dlist)
415         {
416             if(i == index)
417                 return v;
418             i++;
419         }
420         return E.init;
421     }
422 
423     /**
424      * Replaces the element at the specified position in this list with the
425      * specified element.
426      *
427      * @param index index of the element to replace
428      * @param element element to be stored at the specified position
429      * @return the element previously at the specified position
430      * @throws IndexOutOfBoundsException {@inheritDoc}
431      */
432     override E set(int index, E element) {
433         checkElementIndex(index);
434 
435         int i= 0;
436         auto range = _dlist[];
437         range.popFrontN(index);
438         E oldVal = range.front;
439         range.front = element;
440 
441         // for ( ; !range.empty; range.popFront())
442         // {
443         //     if(i == index)
444         //     {
445         //         oldVal = range.front;
446         //         range.front = element;
447         //         break;
448         //     }
449         //     i++;
450         // }
451 
452         return oldVal;
453     }
454 
455     /**
456      * Inserts the specified element at the specified position in this list.
457      * Shifts the element currently at that position (if any) and any
458      * subsequent elements to the right (adds one to their indices).
459      *
460      * @param index index at which the specified element is to be inserted
461      * @param element element to be inserted
462      * @throws IndexOutOfBoundsException {@inheritDoc}
463      */
464     override void add(int index, E element) {
465         checkPositionIndex(index);
466 
467         if (index == _size)
468             linkLast(element);
469         else
470         {
471             auto range = _dlist[];
472             range.popFrontN(index);
473             _dlist.insertBefore(range, element);
474             _size++;
475             modCount++;
476         }
477             // linkBefore(element, node(index));
478     }
479 
480     /**
481      * Removes the element at the specified position in this list.  Shifts any
482      * subsequent elements to the left (subtracts one from their indices).
483      * Returns the element that was removed from the list.
484      *
485      * @param index the index of the element to be removed
486      * @return the element previously at the specified position
487      * @throws IndexOutOfBoundsException {@inheritDoc}
488      */
489      override E removeAt(int index) {
490         checkElementIndex(index);
491         auto range = _dlist[];
492         range.popFrontN(index);
493         auto temp = take(range, 1);
494         _dlist.linearRemove(temp);
495 
496         _size--;
497         modCount++;
498         return temp.front;
499     }
500 
501     /**
502      * Tells if the argument is the index of an existing element.
503      */
504     private bool isElementIndex(int index) {
505         return index >= 0 && index < _size;
506     }
507 
508     /**
509      * Tells if the argument is the index of a valid position for an
510      * iterator or an add operation.
511      */
512     private bool isPositionIndex(int index) {
513         return index >= 0 && index <= _size;
514     }
515 
516     /**
517      * Constructs an IndexOutOfBoundsException detail message.
518      * Of the many possible refactorings of the error handling code,
519      * this "outlining" performs best with both server and client VMs.
520      */
521     private string outOfBoundsMsg(int index) {
522         return "Index: " ~ index.to!string() ~ ", Size: " ~ _size.to!string();
523     }
524 
525     private void checkElementIndex(int index) {
526         if (!isElementIndex(index))
527             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
528     }
529 
530     private void checkPositionIndex(int index) {
531         if (!isPositionIndex(index))
532             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
533     }
534 
535     /**
536      * Returns the (non-null) Node at the specified element index.
537      */
538      
539 //     Node!E node(int index) {
540 //         // assert isElementIndex(index);
541 
542 //         if (index < (_size >> 1)) {
543 //             Node!E x = first;
544 //             for (int i = 0; i < index; i++)
545 //                 x = x.next;
546 //             return x;
547 //         } else {
548 //             Node!E x = last;
549 //             for (int i = _size - 1; i > index; i--)
550 //                 x = x.prev;
551 //             return x;
552 //         }
553 //     }
554 
555     // Search Operations
556 
557     /**
558      * Returns the index of the first occurrence of the specified element
559      * in this list, or -1 if this list does not contain the element.
560      * More formally, returns the lowest index {@code i} such that
561      * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
562      * or -1 if there is no such index.
563      *
564      * @param o element to search for
565      * @return the index of the first occurrence of the specified element in
566      *         this list, or -1 if this list does not contain the element
567      */
568     override int indexOf(E o) {
569         int index = 0;
570         foreach(v; _dlist)
571         {
572             static if( is(E == class))
573             {
574                 if(v == o)
575                     return index;
576             }
577             else
578             {
579                 if(v == o)
580                     return index;
581             }
582             index++;
583         }
584         return -1;
585     }
586 
587     /**
588      * Returns the index of the last occurrence of the specified element
589      * in this list, or -1 if this list does not contain the element.
590      * More formally, returns the highest index {@code i} such that
591      * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
592      * or -1 if there is no such index.
593      *
594      * @param o element to search for
595      * @return the index of the last occurrence of the specified element in
596      *         this list, or -1 if this list does not contain the element
597      */
598     override int lastIndexOf(E o) {
599         int index = _size;
600         auto range = _dlist[];
601         for(; !range.empty; range.popBack())
602         {
603             index--;
604             if(range.back == o)
605                 return index;
606         }
607         return -1;
608     }
609 
610     // Queue operations.
611 
612     /**
613      * Retrieves, but does not remove, the head (first element) of this list.
614      *
615      * @return the head of this list, or {@code null} if this list is empty
616      * @since 1.5
617      */
618     E peek() {        
619         return getFirst();
620     }
621 
622     /**
623      * Retrieves, but does not remove, the head (first element) of this list.
624      *
625      * @return the head of this list
626      * @throws NoSuchElementException if this list is empty
627      * @since 1.5
628      */
629     E element() {
630         return getFirst();
631     }
632 
633     /**
634      * Retrieves and removes the head (first element) of this list.
635      *
636      * @return the head of this list, or {@code null} if this list is empty
637      * @since 1.5
638      */
639     E poll() {
640         return removeFirst();
641     }
642 
643     /**
644      * Retrieves and removes the head (first element) of this list.
645      *
646      * @return the head of this list
647      * @throws NoSuchElementException if this list is empty
648      * @since 1.5
649      */
650     E remove() {
651         return removeFirst();
652     }
653 
654     /**
655      * Adds the specified element as the tail (last element) of this list.
656      *
657      * @param e the element to add
658      * @return {@code true} (as specified by {@link Queue#offer})
659      * @since 1.5
660      */
661     bool offer(E e) {
662         return add(e);
663     }
664 
665     // Deque operations
666     /**
667      * Inserts the specified element at the front of this list.
668      *
669      * @param e the element to insert
670      * @return {@code true} (as specified by {@link Deque#offerFirst})
671      * @since 1.6
672      */
673     bool offerFirst(E e) {
674         addFirst(e);
675         return true;
676     }
677 
678     /**
679      * Inserts the specified element at the end of this list.
680      *
681      * @param e the element to insert
682      * @return {@code true} (as specified by {@link Deque#offerLast})
683      * @since 1.6
684      */
685     bool offerLast(E e) {
686         addLast(e);
687         return true;
688     }
689 
690     /**
691      * Retrieves, but does not remove, the first element of this list,
692      * or returns {@code null} if this list is empty.
693      *
694      * @return the first element of this list, or {@code null}
695      *         if this list is empty
696      * @since 1.6
697      */
698     E peekFirst() {
699         return getFirst();
700      }
701 
702     /**
703      * Retrieves, but does not remove, the last element of this list,
704      * or returns {@code null} if this list is empty.
705      *
706      * @return the last element of this list, or {@code null}
707      *         if this list is empty
708      * @since 1.6
709      */
710     E peekLast() {
711         return getLast();
712     }
713 
714     /**
715      * Retrieves and removes the first element of this list,
716      * or returns {@code null} if this list is empty.
717      *
718      * @return the first element of this list, or {@code null} if
719      *     this list is empty
720      * @since 1.6
721      */
722     E pollFirst() {
723         return removeFirst();
724     }
725 
726     /**
727      * Retrieves and removes the last element of this list,
728      * or returns {@code null} if this list is empty.
729      *
730      * @return the last element of this list, or {@code null} if
731      *     this list is empty
732      * @since 1.6
733      */
734     E pollLast() {
735         return removeLast();
736     }
737 
738     /**
739      * Pushes an element onto the stack represented by this list.  In other
740      * words, inserts the element at the front of this list.
741      *
742      * <p>This method is equivalent to {@link #addFirst}.
743      *
744      * @param e the element to push
745      * @since 1.6
746      */
747     void push(E e) {
748         addFirst(e);
749     }
750 
751     /**
752      * Pops an element from the stack represented by this list.  In other
753      * words, removes and returns the first element of this list.
754      *
755      * <p>This method is equivalent to {@link #removeFirst()}.
756      *
757      * @return the element at the front of this list (which is the top
758      *         of the stack represented by this list)
759      * @throws NoSuchElementException if this list is empty
760      * @since 1.6
761      */
762     E pop() {
763         return removeFirst();
764     }
765 
766     /**
767      * Removes the first occurrence of the specified element in this
768      * list (when traversing the list from head to tail).  If the list
769      * does not contain the element, it is unchanged.
770      *
771      * @param o element to be removed from this list, if present
772      * @return {@code true} if the list contained the specified element
773      * @since 1.6
774      */
775     bool removeFirstOccurrence(E o) {
776         return remove(o);
777     }
778 
779     /**
780      * Removes the last occurrence of the specified element in this
781      * list (when traversing the list from head to tail).  If the list
782      * does not contain the element, it is unchanged.
783      *
784      * @param o element to be removed from this list, if present
785      * @return {@code true} if the list contained the specified element
786      * @since 1.6
787      */
788     // bool removeLastOccurrence(E o) {
789 
790     //     // if (o is null) {
791     //     //     for (Node!E x = last; x !is null; x = x.prev) {
792     //     //         if (x.item is null) {
793     //     //             unlink(x);
794     //     //             return true;
795     //     //         }
796     //     //     }
797     //     // } else {
798     //     //     for (Node!E x = last; x !is null; x = x.prev) {
799     //     //         if (o.equals(x.item)) {
800     //     //             unlink(x);
801     //     //             return true;
802     //     //         }
803     //     //     }
804     //     // }
805     //     // return false;
806     // }
807 
808 
809 // 
810 //     private LinkedList!E superClone() {
811 //         try {
812 //             return (LinkedList!E) super.clone();
813 //         } catch (CloneNotSupportedException e) {
814 //             throw new InternalError(e);
815 //         }
816 //     }
817 
818 //     /**
819 //      * Returns a shallow copy of this {@code LinkedList}. (The elements
820 //      * themselves are not cloned.)
821 //      *
822 //      * @return a shallow copy of this {@code LinkedList} instance
823 //      */
824 //     // Object clone() {
825 //     //     LinkedList!E clone = superClone();
826 
827 //     //     // Put clone into "virgin" state
828 //     //     clone.first = clone.last = null;
829 //     //     clone.size = 0;
830 //     //     clone.modCount = 0;
831 
832 //     //     // Initialize clone with our elements
833 //     //     for (Node!E x = first; x !is null; x = x.next)
834 //     //         clone.add(x.item);
835 
836 //     //     return clone;
837 //     // }
838 
839     /**
840      * Returns an array containing all of the elements in this list
841      * in proper sequence (from first to last element).
842      *
843      * <p>The returned array will be "safe" in that no references to it are
844      * maintained by this list.  (In other words, this method must allocate
845      * a new array).  The caller is thus free to modify the returned array.
846      *
847      * <p>This method acts as bridge between array-based and collection-based
848      * APIs.
849      *
850      * @return an array containing all of the elements in this list
851      *         in proper sequence
852      */
853     override E[] toArray() {
854         // E[] result = new E[_size];
855         // int i = 0;
856         // for (Node!E x = first; x !is null; x = x.next)
857         //     result[i++] = x.item;
858         return _dlist[].array;
859     }
860 
861     override int opApply(scope int delegate(ref E) dg)
862     {
863         int result = 0;
864         foreach(E v; _dlist)
865         {
866             result = dg(v);
867             if(result != 0) return result;
868         }
869         return result;
870     }
871 
872     override bool opEquals(IObject o) {
873         return opEquals(cast(Object) o);
874     }
875     
876     override bool opEquals(Object o) {
877         return super.opEquals(o);
878     }
879 
880     override size_t toHash() @trusted nothrow {
881         return super.toHash();
882     }
883 
884     override string toString() {
885         return super.toString();
886     }    
887 }