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 import hunt.util.Common;
23 
24 import std.conv;
25 import std.container;
26 import std.range;
27 
28 
29 
30 /**
31  * Doubly-linked list implementation of the {@code List} and {@code Deque}
32  * interfaces.  Implements all optional list operations, and permits all
33  * elements (including {@code null}).
34  *
35  * <p>All of the operations perform as could be expected for a doubly-linked
36  * list.  Operations that index into the list will traverse the list from
37  * the beginning or the end, whichever is closer to the specified index.
38  *
39  * <p><strong>Note that this implementation is not synchronized.</strong>
40  * If multiple threads access a linked list concurrently, and at least
41  * one of the threads modifies the list structurally, it <i>must</i> be
42  * synchronized externally.  (A structural modification is any operation
43  * that adds or deletes one or more elements; merely setting the value of
44  * an element is not a structural modification.)  This is typically
45  * accomplished by synchronizing on some object that naturally
46  * encapsulates the list.
47  *
48  * If no such object exists, the list should be "wrapped" using the
49  * {@link Collections#synchronizedList Collections.synchronizedList}
50  * method.  This is best done at creation time, to prevent accidental
51  * unsynchronized access to the list:<pre>
52  *   List list = Collections.synchronizedList(new LinkedList(...));</pre>
53  *
54  * <p>The iterators returned by this class's {@code iterator} and
55  * {@code listIterator} methods are <i>fail-fast</i>: if the list is
56  * structurally modified at any time after the iterator is created, in
57  * any way except through the Iterator's own {@code remove} or
58  * {@code add} methods, the iterator will throw a {@link
59  * ConcurrentModificationException}.  Thus, in the face of concurrent
60  * modification, the iterator fails quickly and cleanly, rather than
61  * risking arbitrary, non-deterministic behavior at an undetermined
62  * time in the future.
63  *
64  * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
65  * as it is, generally speaking, impossible to make any hard guarantees in the
66  * presence of unsynchronized concurrent modification.  Fail-fast iterators
67  * throw {@code ConcurrentModificationException} on a best-effort basis.
68  * Therefore, it would be wrong to write a program that depended on this
69  * exception for its correctness:   <i>the fail-fast behavior of iterators
70  * should be used only to detect bugs.</i>
71  *
72  * <p>This class is a member of the
73  * <a href="{@docRoot}/../technotes/guides/collections/index.html">
74  * Java Collections Framework</a>.
75  *
76  * @author  Josh Bloch
77  * @see     List
78  * @see     ArrayList
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         static if(CompilerHelper.isLessThan(2077)) {
282                 auto range = _dlist[];
283                 for ( ; !range.empty; range.popFront())
284                 {
285                     if (range.front == o)
286                     {
287                         _dlist.stableLinearRemove(take(range, 1));
288                         _size--;
289                         modCount++;
290                         return true;
291                     }
292                 }
293                 return false;
294         } else {
295             if(_dlist.linearRemoveElement(o)) {
296                 _size--;
297                 modCount++;
298                 return true;
299             }   else {
300                 return false;
301             }
302         }
303     }
304 
305     // /**
306     //  * Appends all of the elements in the specified collection to the end of
307     //  * this list, in the order that they are returned by the specified
308     //  * collection's iterator.  The behavior of this operation is undefined if
309     //  * the specified collection is modified while the operation is in
310     //  * progress.  (Note that this will occur if the specified collection is
311     //  * this list, and it's nonempty.)
312     //  *
313     //  * @param c collection containing elements to be added to this list
314     //  * @return {@code true} if this list changed as a result of the call
315     //  * @throws NullPointerException if the specified collection is null
316     //  */
317     // override bool addAll(Collection!E c) {
318 
319     //     bool modified = c.size() > 0;
320     //     foreach (E e ; c) {
321     //         linkLast(e);
322     //     }
323     //     return modified;
324 
325     //     // return addAll(_size, c);
326     // }
327 
328     // bool addAll(E[] c) {
329 
330     //     bool modified = c.length > 0;
331     //     foreach (E e ; c) {
332     //         linkLast(e);
333     //     }
334     //     return modified;
335     // }
336 
337 //     /**
338 //      * Inserts all of the elements in the specified collection into this
339 //      * list, starting at the specified position.  Shifts the element
340 //      * currently at that position (if any) and any subsequent elements to
341 //      * the right (increases their indices).  The new elements will appear
342 //      * in the list in the order that they are returned by the
343 //      * specified collection's iterator.
344 //      *
345 //      * @param index index at which to insert the first element
346 //      *              from the specified collection
347 //      * @param c collection containing elements to be added to this list
348 //      * @return {@code true} if this list changed as a result of the call
349 //      * @throws IndexOutOfBoundsException {@inheritDoc}
350 //      * @throws NullPointerException if the specified collection is null
351 //      */
352 
353 // bool addAll(int index, Collection!E c) {
354 //     throw new NotImplementedException();
355 // }
356 //     bool addAll(int index, Collection<E> c) {
357 //         checkPositionIndex(index);
358 
359 //         Object[] a = c.toArray();
360 //         int numNew = a.length;
361 //         if (numNew == 0)
362 //             return false;
363 
364 //         Node!E pred, succ;
365 //         if (index == _size) {
366 //             succ = null;
367 //             pred = last;
368 //         } else {
369 //             succ = node(index);
370 //             pred = succ.prev;
371 //         }
372 
373 //         for (Object o : a) {
374 //         E e = (E) o;
375 //             Node!E newNode = new Node<>(pred, e, null);
376 //             if (pred is null)
377 //                 first = newNode;
378 //             else
379 //                 pred.next = newNode;
380 //             pred = newNode;
381 //         }
382 
383 //         if (succ is null) {
384 //             last = pred;
385 //         } else {
386 //             pred.next = succ;
387 //             succ.prev = pred;
388 //         }
389 
390 //         _size += numNew;
391 //         modCount++;
392 //         return true;
393 //     }
394 
395     /**
396      * Removes all of the elements from this list.
397      * The list will be empty after this call returns.
398      */
399     override void clear() {
400         _dlist.clear();
401         _size = 0;
402         modCount++;
403     }
404 
405 
406     // Positional Access Operations
407 
408     /**
409      * Returns the element at the specified position in this list.
410      *
411      * @param index index of the element to return
412      * @return the element at the specified position in this list
413      * @throws IndexOutOfBoundsException {@inheritDoc}
414      */
415     override E get(int index) {
416         checkElementIndex(index);
417 
418         int i=0;
419         foreach(v; _dlist)
420         {
421             if(i == index)
422                 return v;
423             i++;
424         }
425         return E.init;
426     }
427 
428     /**
429      * Replaces the element at the specified position in this list with the
430      * specified element.
431      *
432      * @param index index of the element to replace
433      * @param element element to be stored at the specified position
434      * @return the element previously at the specified position
435      * @throws IndexOutOfBoundsException {@inheritDoc}
436      */
437     override E set(int index, E element) {
438         checkElementIndex(index);
439 
440         int i= 0;
441         auto range = _dlist[];
442         range.popFrontN(index);
443         E oldVal = range.front;
444         range.front = element;
445 
446         // for ( ; !range.empty; range.popFront())
447         // {
448         //     if(i == index)
449         //     {
450         //         oldVal = range.front;
451         //         range.front = element;
452         //         break;
453         //     }
454         //     i++;
455         // }
456 
457         return oldVal;
458     }
459 
460     /**
461      * Inserts the specified element at the specified position in this list.
462      * Shifts the element currently at that position (if any) and any
463      * subsequent elements to the right (adds one to their indices).
464      *
465      * @param index index at which the specified element is to be inserted
466      * @param element element to be inserted
467      * @throws IndexOutOfBoundsException {@inheritDoc}
468      */
469     override void add(int index, E element) {
470         checkPositionIndex(index);
471 
472         if (index == _size)
473             linkLast(element);
474         else
475         {
476             auto range = _dlist[];
477             range.popFrontN(index);
478             _dlist.insertBefore(range, element);
479             _size++;
480             modCount++;
481         }
482             // linkBefore(element, node(index));
483     }
484 
485     /**
486      * Removes the element at the specified position in this list.  Shifts any
487      * subsequent elements to the left (subtracts one from their indices).
488      * Returns the element that was removed from the list.
489      *
490      * @param index the index of the element to be removed
491      * @return the element previously at the specified position
492      * @throws IndexOutOfBoundsException {@inheritDoc}
493      */
494      override E removeAt(int index) {
495         checkElementIndex(index);
496         auto range = _dlist[];
497         range.popFrontN(index);
498         auto temp = take(range, 1);
499         _dlist.linearRemove(temp);
500 
501         _size--;
502         modCount++;
503         return temp.front;
504     }
505 
506     /**
507      * Tells if the argument is the index of an existing element.
508      */
509     private bool isElementIndex(int index) {
510         return index >= 0 && index < _size;
511     }
512 
513     /**
514      * Tells if the argument is the index of a valid position for an
515      * iterator or an add operation.
516      */
517     private bool isPositionIndex(int index) {
518         return index >= 0 && index <= _size;
519     }
520 
521     /**
522      * Constructs an IndexOutOfBoundsException detail message.
523      * Of the many possible refactorings of the error handling code,
524      * this "outlining" performs best with both server and client VMs.
525      */
526     private string outOfBoundsMsg(int index) {
527         return "Index: " ~ index.to!string() ~ ", Size: " ~ _size.to!string();
528     }
529 
530     private void checkElementIndex(int index) {
531         if (!isElementIndex(index))
532             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
533     }
534 
535     private void checkPositionIndex(int index) {
536         if (!isPositionIndex(index))
537             throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
538     }
539 
540     /**
541      * Returns the (non-null) Node at the specified element index.
542      */
543      
544 //     Node!E node(int index) {
545 //         // assert isElementIndex(index);
546 
547 //         if (index < (_size >> 1)) {
548 //             Node!E x = first;
549 //             for (int i = 0; i < index; i++)
550 //                 x = x.next;
551 //             return x;
552 //         } else {
553 //             Node!E x = last;
554 //             for (int i = _size - 1; i > index; i--)
555 //                 x = x.prev;
556 //             return x;
557 //         }
558 //     }
559 
560     // Search Operations
561 
562     /**
563      * Returns the index of the first occurrence of the specified element
564      * in this list, or -1 if this list does not contain the element.
565      * More formally, returns the lowest index {@code i} such that
566      * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
567      * or -1 if there is no such index.
568      *
569      * @param o element to search for
570      * @return the index of the first occurrence of the specified element in
571      *         this list, or -1 if this list does not contain the element
572      */
573     override int indexOf(E o) {
574         int index = 0;
575         foreach(v; _dlist)
576         {
577             static if( is(E == class))
578             {
579                 if(v == o)
580                     return index;
581             }
582             else
583             {
584                 if(v == o)
585                     return index;
586             }
587             index++;
588         }
589         return -1;
590     }
591 
592     /**
593      * Returns the index of the last occurrence of the specified element
594      * in this list, or -1 if this list does not contain the element.
595      * More formally, returns the highest index {@code i} such that
596      * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
597      * or -1 if there is no such index.
598      *
599      * @param o element to search for
600      * @return the index of the last occurrence of the specified element in
601      *         this list, or -1 if this list does not contain the element
602      */
603     override int lastIndexOf(E o) {
604         int index = _size;
605         auto range = _dlist[];
606         for(; !range.empty; range.popBack())
607         {
608             index--;
609             if(range.back == o)
610                 return index;
611         }
612         return -1;
613     }
614 
615     // Queue operations.
616 
617     /**
618      * Retrieves, but does not remove, the head (first element) of this list.
619      *
620      * @return the head of this list, or {@code null} if this list is empty
621      */
622     E peek() {        
623         return getFirst();
624     }
625 
626     /**
627      * Retrieves, but does not remove, the head (first element) of this list.
628      *
629      * @return the head of this list
630      * @throws NoSuchElementException if this list is empty
631      */
632     E element() {
633         return getFirst();
634     }
635 
636     /**
637      * Retrieves and removes the head (first element) of this list.
638      *
639      * @return the head of this list, or {@code null} if this list is empty
640      */
641     E poll() {
642         return removeFirst();
643     }
644 
645     /**
646      * Retrieves and removes the head (first element) of this list.
647      *
648      * @return the head of this list
649      * @throws NoSuchElementException if this list is empty
650      */
651     E remove() {
652         return removeFirst();
653     }
654 
655     /**
656      * Adds the specified element as the tail (last element) of this list.
657      *
658      * @param e the element to add
659      * @return {@code true} (as specified by {@link Queue#offer})
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      */
672     bool offerFirst(E e) {
673         addFirst(e);
674         return true;
675     }
676 
677     /**
678      * Inserts the specified element at the end of this list.
679      *
680      * @param e the element to insert
681      * @return {@code true} (as specified by {@link Deque#offerLast})
682      */
683     bool offerLast(E e) {
684         addLast(e);
685         return true;
686     }
687 
688     /**
689      * Retrieves, but does not remove, the first element of this list,
690      * or returns {@code null} if this list is empty.
691      *
692      * @return the first element of this list, or {@code null}
693      *         if this list is empty
694      */
695     E peekFirst() {
696         return getFirst();
697      }
698 
699     /**
700      * Retrieves, but does not remove, the last element of this list,
701      * or returns {@code null} if this list is empty.
702      *
703      * @return the last element of this list, or {@code null}
704      *         if this list is empty
705      */
706     E peekLast() {
707         return getLast();
708     }
709 
710     /**
711      * Retrieves and removes the first element of this list,
712      * or returns {@code null} if this list is empty.
713      *
714      * @return the first element of this list, or {@code null} if
715      *     this list is empty
716      */
717     E pollFirst() {
718         return removeFirst();
719     }
720 
721     /**
722      * Retrieves and removes the last element of this list,
723      * or returns {@code null} if this list is empty.
724      *
725      * @return the last element of this list, or {@code null} if
726      *     this list is empty
727      */
728     E pollLast() {
729         return removeLast();
730     }
731 
732     /**
733      * Pushes an element onto the stack represented by this list.  In other
734      * words, inserts the element at the front of this list.
735      *
736      * <p>This method is equivalent to {@link #addFirst}.
737      *
738      * @param e the element to push
739      */
740     void push(E e) {
741         addFirst(e);
742     }
743 
744     /**
745      * Pops an element from the stack represented by this list.  In other
746      * words, removes and returns the first element of this list.
747      *
748      * <p>This method is equivalent to {@link #removeFirst()}.
749      *
750      * @return the element at the front of this list (which is the top
751      *         of the stack represented by this list)
752      * @throws NoSuchElementException if this list is empty
753      */
754     E pop() {
755         return removeFirst();
756     }
757 
758     /**
759      * Removes the first occurrence of the specified element in this
760      * list (when traversing the list from head to tail).  If the list
761      * does not contain the element, it is unchanged.
762      *
763      * @param o element to be removed from this list, if present
764      * @return {@code true} if the list contained the specified element
765      */
766     bool removeFirstOccurrence(E o) {
767         return remove(o);
768     }
769 
770     /**
771      * Removes the last occurrence of the specified element in this
772      * list (when traversing the list from head to tail).  If the list
773      * does not contain the element, it is unchanged.
774      *
775      * @param o element to be removed from this list, if present
776      * @return {@code true} if the list contained the specified element
777      */
778     // bool removeLastOccurrence(E o) {
779 
780     //     // if (o is null) {
781     //     //     for (Node!E x = last; x !is null; x = x.prev) {
782     //     //         if (x.item is null) {
783     //     //             unlink(x);
784     //     //             return true;
785     //     //         }
786     //     //     }
787     //     // } else {
788     //     //     for (Node!E x = last; x !is null; x = x.prev) {
789     //     //         if (o.equals(x.item)) {
790     //     //             unlink(x);
791     //     //             return true;
792     //     //         }
793     //     //     }
794     //     // }
795     //     // return false;
796     // }
797 
798 
799 // 
800 //     private LinkedList!E superClone() {
801 //         try {
802 //             return (LinkedList!E) super.clone();
803 //         } catch (CloneNotSupportedException e) {
804 //             throw new InternalError(e);
805 //         }
806 //     }
807 
808 //     /**
809 //      * Returns a shallow copy of this {@code LinkedList}. (The elements
810 //      * themselves are not cloned.)
811 //      *
812 //      * @return a shallow copy of this {@code LinkedList} instance
813 //      */
814 //     // Object clone() {
815 //     //     LinkedList!E clone = superClone();
816 
817 //     //     // Put clone into "virgin" state
818 //     //     clone.first = clone.last = null;
819 //     //     clone.size = 0;
820 //     //     clone.modCount = 0;
821 
822 //     //     // Initialize clone with our elements
823 //     //     for (Node!E x = first; x !is null; x = x.next)
824 //     //         clone.add(x.item);
825 
826 //     //     return clone;
827 //     // }
828 
829     /**
830      * Returns an array containing all of the elements in this list
831      * in proper sequence (from first to last element).
832      *
833      * <p>The returned array will be "safe" in that no references to it are
834      * maintained by this list.  (In other words, this method must allocate
835      * a new array).  The caller is thus free to modify the returned array.
836      *
837      * <p>This method acts as bridge between array-based and collection-based
838      * APIs.
839      *
840      * @return an array containing all of the elements in this list
841      *         in proper sequence
842      */
843     override E[] toArray() {
844         // E[] result = new E[_size];
845         // int i = 0;
846         // for (Node!E x = first; x !is null; x = x.next)
847         //     result[i++] = x.item;
848         return _dlist[].array;
849     }
850 
851     override int opApply(scope int delegate(ref E) dg)
852     {
853         int result = 0;
854         foreach(E v; _dlist)
855         {
856             result = dg(v);
857             if(result != 0) return result;
858         }
859         return result;
860     }
861 
862     override bool opEquals(IObject o) {
863         return opEquals(cast(Object) o);
864     }
865     
866     override bool opEquals(Object o) {
867         return super.opEquals(o);
868     }
869 
870     override size_t toHash() @trusted nothrow {
871         return super.toHash();
872     }
873 
874     override string toString() {
875         return super.toString();
876     }    
877 
878     InputRange!E descendingIterator() {
879         throw new NotImplementedException();
880     }
881 }