11const Node = require ( './node' ) ;
22
33/**
4- * Doubly linked list that keeps track of the last and first element
4+ * Doubly linked list that keeps track of
5+ * the last and first element
56 */
67class LinkedList {
78 constructor ( ) {
@@ -11,11 +12,35 @@ class LinkedList {
1112 }
1213
1314 /**
14- * Adds element to the end of the list (tail). Similar to Array.push
15- * Using the element last reference instead of finding last, we can reduce the runtime from O(n) to O(1)
15+ * Adds element to the begining of the list. Similar to Array.unshift
1616 * Runtime: O(1)
1717 * @param {any } value
1818 */
19+ addFirst ( value ) {
20+ const node = new Node ( value ) ;
21+
22+ node . next = this . first ;
23+
24+ if ( this . first ) {
25+ this . first . previous = node ;
26+ } else {
27+ this . last = node ;
28+ }
29+
30+ this . first = node ; // update head
31+ this . size += 1 ;
32+
33+ return node ;
34+ }
35+
36+ /**
37+ * Adds element to the end of the list (tail). Similar to Array.push
38+ * Using the element last reference instead of navigating through the list,
39+ * we can reduced from linear to a constant runtime.
40+ * Runtime: O(1)
41+ * @param {any } value node's value
42+ * @returns {Node } newly created node
43+ */
1944 addLast ( value ) {
2045 const newNode = new Node ( value ) ;
2146
@@ -28,11 +53,45 @@ class LinkedList {
2853 this . last = newNode ;
2954 }
3055
31- this . size ++ ;
56+ this . size += 1 ;
3257
3358 return newNode ;
3459 }
3560
61+ /**
62+ * Insert new element at the given position (index)
63+ *
64+ * @param {any } value new node's value
65+ * @param {Number } position position to insert element
66+ * @returns {Node } new node or 'undefined' if the index is out of bound.
67+ */
68+ add ( value , position = 0 ) {
69+ if ( position === 0 ) {
70+ return this . addFirst ( value ) ;
71+ }
72+
73+ if ( position === this . size ) {
74+ return this . addLast ( value ) ;
75+ }
76+
77+ for ( let current = this . first , index = 0 ;
78+ index <= this . size ;
79+ index += 1 , current = ( current && current . next ) ) {
80+ if ( index === position ) {
81+ const newNode = new Node ( value ) ;
82+ newNode . previous = current . previous ;
83+ newNode . next = current ;
84+
85+ current . previous . next = newNode ;
86+ if ( current . next ) { current . next . previous = newNode ; }
87+ this . size += 1 ;
88+ return newNode ;
89+ }
90+ }
91+
92+ return undefined ; // out of bound index
93+ }
94+
3695 /**
3796 * Removes element from the start of the list (head/root). similar Array.shift
3897 * Runtime: O(1)
@@ -53,28 +112,6 @@ class LinkedList {
53112 this . last = null ;
54113 }
55114
56- /**
57- * Adds element to the begining of the list. Similar to Array.unshift
58- * Runtime: O(1)
59- * @param {any } value
60- */
61- addFirst ( value ) {
62- const node = new Node ( value ) ;
63-
64- node . next = this . first ;
65-
66- if ( this . first ) {
67- this . first . previous = node ;
68- } else {
69- this . last = node ;
70- }
71-
72- this . first = node ; // update head
73- this . size ++ ;
74-
75- return node ;
76- }
77-
78115 /**
79116 * Removes element to the end of the list
80117 * similar to Array.pop
@@ -103,17 +140,38 @@ class LinkedList {
103140 }
104141
105142 /**
106- * Find first occurence of the element matching the value
107- * return index or undefined
143+ * Search by value. It finds first occurrence of
144+ * the element matching the value.
108145 * Runtime: O(n)
109146 * @param {any } value
147+ * @returns {number } return index or undefined
110148 */
111- contains ( value ) {
112- for ( let current = this . first , index = 0 ; current ; index ++ , current = current . next ) {
149+ indexOf ( value ) {
150+ for ( let current = this . first , index = 0 ;
151+ current ;
152+ index += 1 , current = current . next ) {
113153 if ( current . value === value ) {
114154 return index ;
115155 }
116156 }
157+ return undefined ; // not found
158+ }
159+
160+ /**
161+ * Search by index
162+ * Runtime: O(n)
163+ * @param {Number } index position of the element
164+ * @returns {Node } element at the specified position in this list.
165+ */
166+ get ( index = 0 ) {
167+ for ( let current = this . first , position = 0 ;
168+ current ;
169+ position += 1 , current = current . next ) {
170+ if ( position === index ) {
171+ return current ;
172+ }
173+ }
174+ return undefined ; // not found
117175 }
118176
119177 /**
@@ -138,34 +196,6 @@ class LinkedList {
138196 }
139197 }
140198 }
141-
142- /**
143- * Insert new element on the given position
144- * Returns index if it failed to insert element (index out of bounds), otherwise undefined
145- * @param {any } value new node's value
146- * @param {Number } index position to insert element
147- */
148- add ( value , index = 0 ) {
149- if ( index === 0 ) {
150- return this . addFirst ( value ) ;
151- }
152-
153- for ( let current = this . first , i = 0 ; i <= this . size ; i ++ , current = ( current && current . next ) ) {
154- if ( i === index ) {
155- if ( i === this . size ) { // if it doesn't have next it means that it is the last
156- return this . addLast ( value ) ;
157- }
158- const newNode = new Node ( value ) ;
159- newNode . previous = current . previous ;
160- newNode . next = current ;
161-
162- current . previous . next = newNode ;
163- if ( current . next ) { current . next . previous = newNode ; }
164- this . size ++ ;
165- return newNode ;
166- }
167- }
168- }
169199}
170200
171201// Aliases
0 commit comments