collect-your-stuff 1.3.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/collections/arrayable/Arrayable.d.ts +2 -2
- package/dist/collections/arrayable/Arrayable.js +10 -0
- package/dist/collections/arrayable/Arrayable.min.js +1 -1
- package/dist/collections/doubly-linked-list/DoublyLinkedList.d.ts +14 -8
- package/dist/collections/doubly-linked-list/DoublyLinkedList.js +91 -56
- package/dist/collections/doubly-linked-list/DoublyLinkedList.min.js +1 -1
- package/dist/collections/linked-list/LinkedList.d.ts +14 -3
- package/dist/collections/linked-list/LinkedList.js +76 -32
- package/dist/collections/linked-list/LinkedList.min.js +1 -1
- package/dist/collections/linked-tree-list/LinkedTreeList.d.ts +9 -3
- package/dist/collections/linked-tree-list/LinkedTreeList.js +19 -21
- package/dist/collections/linked-tree-list/LinkedTreeList.min.js +1 -1
- package/dist/collections/queue/Queue.d.ts +35 -42
- package/dist/collections/queue/Queue.js +64 -80
- package/dist/collections/queue/Queue.min.js +1 -1
- package/dist/collections/queue/TaskQueue.d.ts +68 -0
- package/dist/collections/queue/TaskQueue.js +137 -0
- package/dist/collections/queue/TaskQueue.min.js +1 -0
- package/dist/collections/stack/Stack.d.ts +40 -40
- package/dist/collections/stack/Stack.js +73 -52
- package/dist/collections/stack/Stack.min.js +1 -1
- package/dist/collections/stack/TaskStack.d.ts +65 -0
- package/dist/collections/stack/TaskStack.js +107 -0
- package/dist/collections/stack/TaskStack.min.js +1 -0
- package/dist/main.d.ts +7 -1
- package/dist/main.js +16 -0
- package/dist/main.min.js +1 -1
- package/dist/recipes/IsQueue.d.ts +37 -0
- package/dist/recipes/IsQueue.js +5 -0
- package/dist/recipes/IsQueue.min.js +1 -0
- package/dist/recipes/IsStack.d.ts +36 -0
- package/dist/recipes/IsStack.js +5 -0
- package/dist/recipes/IsStack.min.js +1 -0
- package/package.json +1 -1
|
@@ -79,14 +79,14 @@ export declare class Arrayable implements IsArrayable<ArrayElement>, Iterable<Ar
|
|
|
79
79
|
* @param {ArrayElement} after The existing last node
|
|
80
80
|
* @returns {Arrayable}
|
|
81
81
|
*/
|
|
82
|
-
append(node: ArrayElement | any, after?: ArrayElement): Arrayable;
|
|
82
|
+
append(node: ArrayElement | any, after?: ArrayElement | null): Arrayable;
|
|
83
83
|
/**
|
|
84
84
|
* Add a node (or data) before the given (or first) node in the list.
|
|
85
85
|
* @param {ArrayElement|*} node The new node to add to the start of the list
|
|
86
86
|
* @param {ArrayElement} before The existing first node
|
|
87
87
|
* @returns {Arrayable}
|
|
88
88
|
*/
|
|
89
|
-
prepend(node: ArrayElement | any, before?: ArrayElement): Arrayable;
|
|
89
|
+
prepend(node: ArrayElement | any, before?: ArrayElement | null): Arrayable;
|
|
90
90
|
/**
|
|
91
91
|
* Remove an element from this arrayable.
|
|
92
92
|
* @param {ArrayElement} node The node we wish to remove (and it will be returned after removal)
|
|
@@ -127,6 +127,11 @@ class Arrayable {
|
|
|
127
127
|
* @returns {Arrayable}
|
|
128
128
|
*/
|
|
129
129
|
append (node, after = this.last) {
|
|
130
|
+
if (after === this.last) {
|
|
131
|
+
// Adding to the end does not need to search for where that is
|
|
132
|
+
this.innerList.push(this.elementClass.make(node, this.elementClass))
|
|
133
|
+
return this
|
|
134
|
+
}
|
|
130
135
|
return this.insertAfter(after, node)
|
|
131
136
|
}
|
|
132
137
|
|
|
@@ -137,6 +142,11 @@ class Arrayable {
|
|
|
137
142
|
* @returns {Arrayable}
|
|
138
143
|
*/
|
|
139
144
|
prepend (node, before = this.first) {
|
|
145
|
+
if (before === this.first) {
|
|
146
|
+
// Adding to the start does not need to search for where that is
|
|
147
|
+
this.innerList.unshift(this.elementClass.make(node, this.elementClass))
|
|
148
|
+
return this
|
|
149
|
+
}
|
|
140
150
|
return this.insertBefore(before, node)
|
|
141
151
|
}
|
|
142
152
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.Arrayable=void 0;var _ArrayElement=require("./ArrayElement"),_ArrayIterator=require("../../recipes/ArrayIterator");class Arrayable{constructor(e=_ArrayElement.ArrayElement){this.classType=Arrayable,this.innerList=[],this.initialized=!1,this.elementClass=e}indexOfElement(e){const t=this.innerList.indexOf(e);if(t<0)throw new Error("The reference element is not in this list.");return t}initialize(e){return this.initialized?(console.warn("Attempt to initialize non-empty list."),this):(this.initialized=!0,this.innerList=e,this)}get list(){return this.innerList}get first(){return this.length?this.innerList[0]:null}get last(){return this.length?this.innerList[this.length-1]:null}get length(){return this.innerList.length}insertAfter(e,t){const
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.Arrayable=void 0;var _ArrayElement=require("./ArrayElement"),_ArrayIterator=require("../../recipes/ArrayIterator");class Arrayable{constructor(e=_ArrayElement.ArrayElement){this.classType=Arrayable,this.innerList=[],this.initialized=!1,this.elementClass=e}indexOfElement(e){const t=this.innerList.indexOf(e);if(t<0)throw new Error("The reference element is not in this list.");return t}initialize(e){return this.initialized?(console.warn("Attempt to initialize non-empty list."),this):(this.initialized=!0,this.innerList=e,this)}get list(){return this.innerList}get first(){return this.length?this.innerList[0]:null}get last(){return this.length?this.innerList[this.length-1]:null}get length(){return this.innerList.length}insertAfter(e,t){const i=null==e?-1:this.indexOfElement(e);return this.innerList.splice(i+1,0,this.elementClass.make(t,this.elementClass)),this}insertBefore(e,t){const i=null==e?this.length:this.indexOfElement(e);return this.innerList.splice(i,0,this.elementClass.make(t,this.elementClass)),this}append(e,t=this.last){return t===this.last?(this.innerList.push(this.elementClass.make(e,this.elementClass)),this):this.insertAfter(t,e)}prepend(e,t=this.first){return t===this.first?(this.innerList.unshift(this.elementClass.make(e,this.elementClass)),this):this.insertBefore(t,e)}remove(e){const t=this.innerList.indexOf(e);return t<0?null:(this.innerList.splice(t,1),e)}item(e){if(e>=this.length)return null;if(e>=0)return this.innerList[e];const t=this.length+e;return t<0?null:this.innerList[t]}forEach(e,t=this){for(let i=0;i<t.length;++i)e(t.item(i),i,t);return t}[Symbol.iterator](){return new _ArrayIterator.ArrayIterator(this.innerList,0)}}exports.Arrayable=Arrayable,Arrayable.fromArray=(e=[],t=_ArrayElement.ArrayElement,i=Arrayable)=>new i(t).initialize(t.fromArray(e).head);
|
|
@@ -20,6 +20,10 @@ export declare class DoublyLinkedList implements IsArrayable<DoubleLinker>, Iter
|
|
|
20
20
|
initialized: boolean;
|
|
21
21
|
/** The class used to wrap the data given to this list as linkers. */
|
|
22
22
|
linkerClass: typeof DoubleLinker;
|
|
23
|
+
/** The last linker, remembered so that adding to the end does not need to walk the whole list (null when not known yet). */
|
|
24
|
+
private tailCache;
|
|
25
|
+
/** The number of linkers, kept up to date by the list's own methods so that the length does not need to walk the whole list (null when not known yet). */
|
|
26
|
+
private countCache;
|
|
23
27
|
/**
|
|
24
28
|
* Create the new DoublyLinkedList instance.
|
|
25
29
|
* @param {DoubleLinker} [linkerClass=DoubleLinker] The class used to wrap given data as linkers.
|
|
@@ -40,14 +44,15 @@ export declare class DoublyLinkedList implements IsArrayable<DoubleLinker>, Iter
|
|
|
40
44
|
* Retrieve the first DoubleLinker in the list.
|
|
41
45
|
* @returns {DoubleLinker}
|
|
42
46
|
*/
|
|
43
|
-
get first(): DoubleLinker;
|
|
47
|
+
get first(): DoubleLinker | null;
|
|
44
48
|
/**
|
|
45
|
-
* Retrieve the last DoubleLinker in the list.
|
|
49
|
+
* Retrieve the last DoubleLinker in the list. The end is remembered, so this does not walk the list.
|
|
46
50
|
* @returns {DoubleLinker}
|
|
47
51
|
*/
|
|
48
|
-
get last(): DoubleLinker;
|
|
52
|
+
get last(): DoubleLinker | null;
|
|
49
53
|
/**
|
|
50
|
-
* Return the length of the list.
|
|
54
|
+
* Return the length of the list. It is kept up to date by the list's own methods, so this does not walk the list
|
|
55
|
+
* (call reset() after linkers were changed directly).
|
|
51
56
|
* @returns {number}
|
|
52
57
|
*/
|
|
53
58
|
get length(): number;
|
|
@@ -84,12 +89,13 @@ export declare class DoublyLinkedList implements IsArrayable<DoubleLinker>, Iter
|
|
|
84
89
|
* @param {DoubleLinker} node The node we wish to remove (and it will be returned after removal)
|
|
85
90
|
* @return {DoubleLinker}
|
|
86
91
|
*/
|
|
87
|
-
remove(node: DoubleLinker): DoubleLinker;
|
|
92
|
+
remove(node: DoubleLinker | null): DoubleLinker | null;
|
|
88
93
|
/**
|
|
89
|
-
* Refresh all references and return head
|
|
90
|
-
*
|
|
94
|
+
* Refresh all references (the head, the end and the length) by walking the list once, and return the head. The list's
|
|
95
|
+
* own methods keep these up to date, so this is only needed after linkers were changed directly.
|
|
96
|
+
* @return {DoubleLinker|null}
|
|
91
97
|
*/
|
|
92
|
-
reset(): DoubleLinker;
|
|
98
|
+
reset(): DoubleLinker | null;
|
|
93
99
|
/**
|
|
94
100
|
* Retrieve a DoubleLinker item from this list by numeric index, otherwise return null.
|
|
95
101
|
* @param {number} index The integer number for retrieving a node by position.
|
|
@@ -32,6 +32,10 @@ class DoublyLinkedList {
|
|
|
32
32
|
this.innerList = null
|
|
33
33
|
/** Whether the inner list has been initialized (it can only be initialized once). */
|
|
34
34
|
this.initialized = false
|
|
35
|
+
/** The last linker, remembered so that adding to the end does not need to walk the whole list (null when not known yet). */
|
|
36
|
+
this.tailCache = null
|
|
37
|
+
/** The number of linkers, kept up to date by the list's own methods so that the length does not need to walk the whole list (null when not known yet). */
|
|
38
|
+
this.countCache = null
|
|
35
39
|
this.linkerClass = linkerClass
|
|
36
40
|
}
|
|
37
41
|
|
|
@@ -58,38 +62,45 @@ class DoublyLinkedList {
|
|
|
58
62
|
* @returns {DoubleLinker}
|
|
59
63
|
*/
|
|
60
64
|
get first () {
|
|
61
|
-
|
|
65
|
+
let head = this.innerList
|
|
66
|
+
if (head === null) {
|
|
67
|
+
return null
|
|
68
|
+
}
|
|
69
|
+
// innerList is normally the head already, walking back also finds anything linked on before it outside of this list
|
|
70
|
+
while (head.prev !== null) {
|
|
71
|
+
head = head.prev
|
|
72
|
+
}
|
|
73
|
+
this.innerList = head
|
|
74
|
+
return head
|
|
62
75
|
}
|
|
63
76
|
|
|
64
77
|
/**
|
|
65
|
-
* Retrieve the last DoubleLinker in the list.
|
|
78
|
+
* Retrieve the last DoubleLinker in the list. The end is remembered, so this does not walk the list.
|
|
66
79
|
* @returns {DoubleLinker}
|
|
67
80
|
*/
|
|
68
81
|
get last () {
|
|
69
|
-
|
|
70
|
-
if (tail === null) {
|
|
82
|
+
if (this.innerList === null) {
|
|
71
83
|
return null
|
|
72
84
|
}
|
|
73
|
-
let
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
85
|
+
let tail = this.tailCache !== null ? this.tailCache : this.innerList
|
|
86
|
+
// The remembered tail is normally the end already, walking on from it also finds anything linked on outside of this list
|
|
87
|
+
while (tail.next !== null) {
|
|
88
|
+
tail = tail.next
|
|
77
89
|
}
|
|
90
|
+
this.tailCache = tail
|
|
78
91
|
return tail
|
|
79
92
|
}
|
|
80
93
|
|
|
81
94
|
/**
|
|
82
|
-
* Return the length of the list.
|
|
95
|
+
* Return the length of the list. It is kept up to date by the list's own methods, so this does not walk the list
|
|
96
|
+
* (call reset() after linkers were changed directly).
|
|
83
97
|
* @returns {number}
|
|
84
98
|
*/
|
|
85
99
|
get length () {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
while (current !== null) {
|
|
89
|
-
++length
|
|
90
|
-
current = current.next
|
|
100
|
+
if (this.countCache === null) {
|
|
101
|
+
this.reset()
|
|
91
102
|
}
|
|
92
|
-
return
|
|
103
|
+
return this.countCache
|
|
93
104
|
}
|
|
94
105
|
|
|
95
106
|
/**
|
|
@@ -103,24 +114,31 @@ class DoublyLinkedList {
|
|
|
103
114
|
if (node === null || typeof node === 'undefined') {
|
|
104
115
|
// After nothing means at the start of the list
|
|
105
116
|
const head = this.first
|
|
117
|
+
newNode.prev = null
|
|
106
118
|
newNode.next = head
|
|
107
119
|
if (head) {
|
|
108
120
|
head.prev = newNode
|
|
121
|
+
} else {
|
|
122
|
+
this.tailCache = newNode
|
|
109
123
|
}
|
|
110
124
|
this.innerList = newNode
|
|
111
|
-
|
|
125
|
+
} else {
|
|
126
|
+
// Ensure the next reference of this node is assigned to the new node
|
|
127
|
+
newNode.next = node.next
|
|
128
|
+
// Ensure this node is assigned as the prev reference of the new node
|
|
129
|
+
newNode.prev = node
|
|
130
|
+
// Then set this node's next reference to the new node
|
|
131
|
+
node.next = newNode
|
|
132
|
+
if (newNode.next) {
|
|
133
|
+
// Update the next reference to ensure circular reference for prev points to the new node
|
|
134
|
+
newNode.next.prev = newNode
|
|
135
|
+
} else {
|
|
136
|
+
this.tailCache = newNode
|
|
137
|
+
}
|
|
112
138
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
// Ensure this node is assigned as the prev reference of the new node
|
|
116
|
-
newNode.prev = node
|
|
117
|
-
// Then set this node's next reference to the new node
|
|
118
|
-
node.next = newNode
|
|
119
|
-
if (newNode.next) {
|
|
120
|
-
// Update the next reference to ensure circular reference for prev points to the new node
|
|
121
|
-
newNode.next.prev = newNode
|
|
139
|
+
if (this.countCache !== null) {
|
|
140
|
+
++this.countCache
|
|
122
141
|
}
|
|
123
|
-
this.reset()
|
|
124
142
|
return this
|
|
125
143
|
}
|
|
126
144
|
|
|
@@ -135,26 +153,31 @@ class DoublyLinkedList {
|
|
|
135
153
|
if (node === null || typeof node === 'undefined') {
|
|
136
154
|
// Before nothing means at the end of the list
|
|
137
155
|
const tail = this.last
|
|
156
|
+
newNode.next = null
|
|
157
|
+
newNode.prev = tail
|
|
138
158
|
if (tail === null) {
|
|
139
159
|
this.innerList = newNode
|
|
140
160
|
} else {
|
|
141
161
|
tail.next = newNode
|
|
142
|
-
newNode.prev = tail
|
|
143
162
|
}
|
|
144
|
-
this.
|
|
145
|
-
|
|
163
|
+
this.tailCache = newNode
|
|
164
|
+
} else {
|
|
165
|
+
// The new node will reference this prev node as prev
|
|
166
|
+
newNode.prev = node.prev
|
|
167
|
+
// The new node will reference this node as next
|
|
168
|
+
newNode.next = node
|
|
169
|
+
// This prev will reference the new node
|
|
170
|
+
node.prev = newNode
|
|
171
|
+
if (newNode.prev) {
|
|
172
|
+
// Update the prev reference to ensure circular reference for next points to the new node
|
|
173
|
+
newNode.prev.next = newNode
|
|
174
|
+
} else {
|
|
175
|
+
this.innerList = newNode
|
|
176
|
+
}
|
|
146
177
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
// The new node will reference this node as next
|
|
150
|
-
newNode.next = node
|
|
151
|
-
// This prev will reference the new node
|
|
152
|
-
node.prev = newNode
|
|
153
|
-
if (newNode.prev) {
|
|
154
|
-
// Update the prev reference to ensure circular reference for next points to the new node
|
|
155
|
-
newNode.prev.next = newNode
|
|
178
|
+
if (this.countCache !== null) {
|
|
179
|
+
++this.countCache
|
|
156
180
|
}
|
|
157
|
-
this.reset()
|
|
158
181
|
return this
|
|
159
182
|
}
|
|
160
183
|
|
|
@@ -184,7 +207,7 @@ class DoublyLinkedList {
|
|
|
184
207
|
* @return {DoubleLinker}
|
|
185
208
|
*/
|
|
186
209
|
remove (node) {
|
|
187
|
-
if (node === null) {
|
|
210
|
+
if (node === null || typeof node === 'undefined') {
|
|
188
211
|
return null
|
|
189
212
|
}
|
|
190
213
|
if (node.prev) {
|
|
@@ -200,35 +223,47 @@ class DoublyLinkedList {
|
|
|
200
223
|
if (this.innerList === node) {
|
|
201
224
|
this.innerList = node.next || node.prev || null
|
|
202
225
|
}
|
|
203
|
-
|
|
204
|
-
|
|
226
|
+
if (this.tailCache === node) {
|
|
227
|
+
this.tailCache = node.prev
|
|
228
|
+
}
|
|
229
|
+
if (this.innerList === null) {
|
|
230
|
+
this.tailCache = null
|
|
231
|
+
}
|
|
232
|
+
if (this.countCache !== null) {
|
|
233
|
+
--this.countCache
|
|
234
|
+
}
|
|
205
235
|
return node
|
|
206
236
|
}
|
|
207
237
|
|
|
208
238
|
/**
|
|
209
|
-
* Refresh all references and return head
|
|
210
|
-
*
|
|
239
|
+
* Refresh all references (the head, the end and the length) by walking the list once, and return the head. The list's
|
|
240
|
+
* own methods keep these up to date, so this is only needed after linkers were changed directly.
|
|
241
|
+
* @return {DoubleLinker|null}
|
|
211
242
|
*/
|
|
212
243
|
reset () {
|
|
213
244
|
// Start at the pointer for the list
|
|
214
245
|
let pointer = this.innerList
|
|
215
246
|
if (pointer === null) {
|
|
247
|
+
this.countCache = 0
|
|
248
|
+
this.tailCache = null
|
|
216
249
|
return null
|
|
217
250
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
pointer = next
|
|
222
|
-
next = pointer.next
|
|
223
|
-
}
|
|
224
|
-
let prev = pointer.prev
|
|
225
|
-
// From final reference, follow references back to the beginning
|
|
226
|
-
while (prev !== null) {
|
|
227
|
-
pointer = prev
|
|
228
|
-
prev = pointer.prev
|
|
251
|
+
// Follow references back to the beginning
|
|
252
|
+
while (pointer.prev !== null) {
|
|
253
|
+
pointer = pointer.prev
|
|
229
254
|
}
|
|
230
|
-
//
|
|
255
|
+
// We are pointing to the true head, now count along to the end to find the tail and the length
|
|
231
256
|
this.innerList = pointer
|
|
257
|
+
let count = 0
|
|
258
|
+
let tail = pointer
|
|
259
|
+
let current = pointer
|
|
260
|
+
while (current !== null) {
|
|
261
|
+
++count
|
|
262
|
+
tail = current
|
|
263
|
+
current = current.next
|
|
264
|
+
}
|
|
265
|
+
this.countCache = count
|
|
266
|
+
this.tailCache = tail
|
|
232
267
|
return pointer
|
|
233
268
|
}
|
|
234
269
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.DoublyLinkedList=void 0,require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.for-each.js");var _DoubleLinker=require("./DoubleLinker"),_DoubleLinkerIterator=require("../../recipes/DoubleLinkerIterator"),_LinkedList=require("../linked-list/LinkedList");class DoublyLinkedList{constructor(e=_DoubleLinker.DoubleLinker){this.classType=DoublyLinkedList,this.innerList=null,this.initialized=!1,this.linkerClass=e}initialize(e){return _LinkedList.LinkedList.prototype.initialize.call(this,e)}get list(){return this.innerList}get first(){
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.DoublyLinkedList=void 0,require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.for-each.js");var _DoubleLinker=require("./DoubleLinker"),_DoubleLinkerIterator=require("../../recipes/DoubleLinkerIterator"),_LinkedList=require("../linked-list/LinkedList");class DoublyLinkedList{constructor(e=_DoubleLinker.DoubleLinker){this.classType=DoublyLinkedList,this.innerList=null,this.initialized=!1,this.tailCache=null,this.countCache=null,this.linkerClass=e}initialize(e){return _LinkedList.LinkedList.prototype.initialize.call(this,e)}get list(){return this.innerList}get first(){let e=this.innerList;if(null===e)return null;for(;null!==e.prev;)e=e.prev;return this.innerList=e,e}get last(){if(null===this.innerList)return null;let e=null!==this.tailCache?this.tailCache:this.innerList;for(;null!==e.next;)e=e.next;return this.tailCache=e,e}get length(){return null===this.countCache&&this.reset(),this.countCache}insertAfter(e,t){if(t=this.linkerClass.make(t,this.linkerClass),null==e){const e=this.first;t.prev=null,t.next=e,e?e.prev=t:this.tailCache=t,this.innerList=t}else t.next=e.next,t.prev=e,e.next=t,t.next?t.next.prev=t:this.tailCache=t;return null!==this.countCache&&++this.countCache,this}insertBefore(e,t){if(t=this.linkerClass.make(t,this.linkerClass),null==e){const e=this.last;t.next=null,t.prev=e,null===e?this.innerList=t:e.next=t,this.tailCache=t}else t.prev=e.prev,t.next=e,e.prev=t,t.prev?t.prev.next=t:this.innerList=t;return null!==this.countCache&&++this.countCache,this}append(e,t=this.last){return this.insertAfter(t,e)}prepend(e,t=this.first){return this.insertBefore(t,e)}remove(e){return null==e?null:(e.prev&&(e.prev.next=e.next),e.next&&(e.next.prev=e.prev),this.innerList===e&&(this.innerList=e.next||e.prev||null),this.tailCache===e&&(this.tailCache=e.prev),null===this.innerList&&(this.tailCache=null),null!==this.countCache&&--this.countCache,e)}reset(){let e=this.innerList;if(null===e)return this.countCache=0,this.tailCache=null,null;for(;null!==e.prev;)e=e.prev;this.innerList=e;let t=0,i=e,n=e;for(;null!==n;)++t,i=n,n=n.next;return this.countCache=t,this.tailCache=i,e}item(e){if(e>=0){let t=this.first,i=-1;for(;++i<e&&null!==t;)t=t.next;return i===e?t:null}let t=this.last,i=this.length;const n=this.length+e;if(n<0)return null;for(;--i>n&&null!==t;)t=t.prev;return i===n?t:null}forEach(e,t=this){return _LinkedList.LinkedList.prototype.forEach.call(this,e,t)}[Symbol.iterator](){let e=this.first;return new _DoubleLinkerIterator.DoubleLinkerIterator(e)}}exports.DoublyLinkedList=DoublyLinkedList,DoublyLinkedList.fromArray=(e=[],t=_DoubleLinker.DoubleLinker,i=DoublyLinkedList)=>_LinkedList.LinkedList.fromArray(e,t,i);
|
|
@@ -20,6 +20,10 @@ export declare class LinkedList implements IsArrayable<Linker>, Iterable<Linker>
|
|
|
20
20
|
initialized: boolean;
|
|
21
21
|
/** The class used to wrap the data given to this list as linkers. */
|
|
22
22
|
linkerClass: typeof Linker;
|
|
23
|
+
/** The last linker, remembered so that adding to the end does not need to walk the whole list (null when not known yet). */
|
|
24
|
+
private tailCache;
|
|
25
|
+
/** The number of linkers, kept up to date by the list's own methods so that the length does not need to walk the whole list (null when not known yet). */
|
|
26
|
+
private countCache;
|
|
23
27
|
/**
|
|
24
28
|
* Create the new LinkedList instance.
|
|
25
29
|
* @param {Linker} [linkerClass=Linker] The class used to wrap given data as linkers.
|
|
@@ -42,12 +46,13 @@ export declare class LinkedList implements IsArrayable<Linker>, Iterable<Linker>
|
|
|
42
46
|
*/
|
|
43
47
|
get first(): Linker;
|
|
44
48
|
/**
|
|
45
|
-
* Retrieve the last Linker in the list.
|
|
49
|
+
* Retrieve the last Linker in the list. The end is remembered, so this does not walk the list.
|
|
46
50
|
* @returns {Linker}
|
|
47
51
|
*/
|
|
48
|
-
get last(): Linker;
|
|
52
|
+
get last(): Linker | null;
|
|
49
53
|
/**
|
|
50
|
-
* Return the length of the list.
|
|
54
|
+
* Return the length of the list. It is kept up to date by the list's own methods, so this does not walk the list
|
|
55
|
+
* (call reset() after linkers were changed directly).
|
|
51
56
|
* @returns {number}
|
|
52
57
|
*/
|
|
53
58
|
get length(): number;
|
|
@@ -86,6 +91,12 @@ export declare class LinkedList implements IsArrayable<Linker>, Iterable<Linker>
|
|
|
86
91
|
* @return {Linker|null} The removed node, or null when it was not in this list (nothing is removed)
|
|
87
92
|
*/
|
|
88
93
|
remove(node: Linker | null): Linker | null;
|
|
94
|
+
/**
|
|
95
|
+
* Refresh the remembered end and length of the list by walking it once. The list's own methods keep these up to date,
|
|
96
|
+
* so this is only needed after linkers were changed directly (for example by setting next on a linker).
|
|
97
|
+
* @return {Linker|null} The first linker of the list
|
|
98
|
+
*/
|
|
99
|
+
reset(): Linker | null;
|
|
89
100
|
/**
|
|
90
101
|
* Retrieve a Linker item from this list by numeric index, otherwise return null.
|
|
91
102
|
* @param {number} index The integer number for retrieving a node by position.
|
|
@@ -23,6 +23,10 @@ class LinkedList {
|
|
|
23
23
|
this.innerList = null
|
|
24
24
|
/** Whether the inner list has been initialized (it can only be initialized once). */
|
|
25
25
|
this.initialized = false
|
|
26
|
+
/** The last linker, remembered so that adding to the end does not need to walk the whole list (null when not known yet). */
|
|
27
|
+
this.tailCache = null
|
|
28
|
+
/** The number of linkers, kept up to date by the list's own methods so that the length does not need to walk the whole list (null when not known yet). */
|
|
29
|
+
this.countCache = null
|
|
26
30
|
this.linkerClass = linkerClass
|
|
27
31
|
}
|
|
28
32
|
|
|
@@ -53,34 +57,32 @@ class LinkedList {
|
|
|
53
57
|
}
|
|
54
58
|
|
|
55
59
|
/**
|
|
56
|
-
* Retrieve the last Linker in the list.
|
|
60
|
+
* Retrieve the last Linker in the list. The end is remembered, so this does not walk the list.
|
|
57
61
|
* @returns {Linker}
|
|
58
62
|
*/
|
|
59
63
|
get last () {
|
|
60
|
-
|
|
61
|
-
if (tail === null) {
|
|
64
|
+
if (this.innerList === null) {
|
|
62
65
|
return null
|
|
63
66
|
}
|
|
64
|
-
let
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
67
|
+
let tail = this.tailCache !== null ? this.tailCache : this.innerList
|
|
68
|
+
// The remembered tail is normally the end already, walking on from it also finds anything linked on outside of this list
|
|
69
|
+
while (tail.next !== null) {
|
|
70
|
+
tail = tail.next
|
|
68
71
|
}
|
|
72
|
+
this.tailCache = tail
|
|
69
73
|
return tail
|
|
70
74
|
}
|
|
71
75
|
|
|
72
76
|
/**
|
|
73
|
-
* Return the length of the list.
|
|
77
|
+
* Return the length of the list. It is kept up to date by the list's own methods, so this does not walk the list
|
|
78
|
+
* (call reset() after linkers were changed directly).
|
|
74
79
|
* @returns {number}
|
|
75
80
|
*/
|
|
76
81
|
get length () {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
while (current !== null) {
|
|
80
|
-
++length
|
|
81
|
-
current = current.next
|
|
82
|
+
if (this.countCache === null) {
|
|
83
|
+
this.reset()
|
|
82
84
|
}
|
|
83
|
-
return
|
|
85
|
+
return this.countCache
|
|
84
86
|
}
|
|
85
87
|
|
|
86
88
|
/**
|
|
@@ -94,11 +96,20 @@ class LinkedList {
|
|
|
94
96
|
if (node === null || typeof node === 'undefined') {
|
|
95
97
|
// After nothing means at the start of the list
|
|
96
98
|
newNode.next = this.innerList
|
|
99
|
+
if (this.innerList === null) {
|
|
100
|
+
this.tailCache = newNode
|
|
101
|
+
}
|
|
97
102
|
this.innerList = newNode
|
|
98
|
-
|
|
103
|
+
} else {
|
|
104
|
+
newNode.next = node.next
|
|
105
|
+
node.next = newNode
|
|
106
|
+
if (newNode.next === null) {
|
|
107
|
+
this.tailCache = newNode
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (this.countCache !== null) {
|
|
111
|
+
++this.countCache
|
|
99
112
|
}
|
|
100
|
-
newNode.next = node.next
|
|
101
|
-
node.next = newNode
|
|
102
113
|
return this
|
|
103
114
|
}
|
|
104
115
|
|
|
@@ -114,27 +125,32 @@ class LinkedList {
|
|
|
114
125
|
if (node === null || typeof node === 'undefined') {
|
|
115
126
|
// Before nothing means at the end of the list
|
|
116
127
|
const tail = this.last
|
|
128
|
+
newNode.next = null
|
|
117
129
|
if (tail === null) {
|
|
118
130
|
this.innerList = newNode
|
|
119
131
|
} else {
|
|
120
132
|
tail.next = newNode
|
|
121
133
|
}
|
|
122
|
-
|
|
123
|
-
}
|
|
124
|
-
let prevNode = null
|
|
125
|
-
let currentNode = this.first
|
|
126
|
-
while (currentNode !== null && currentNode !== node) {
|
|
127
|
-
prevNode = currentNode
|
|
128
|
-
currentNode = currentNode.next
|
|
129
|
-
}
|
|
130
|
-
if (currentNode === null) {
|
|
131
|
-
throw new Error('The reference node is not in this list.')
|
|
132
|
-
}
|
|
133
|
-
newNode.next = node
|
|
134
|
-
if (prevNode) {
|
|
135
|
-
prevNode.next = newNode
|
|
134
|
+
this.tailCache = newNode
|
|
136
135
|
} else {
|
|
137
|
-
|
|
136
|
+
let prevNode = null
|
|
137
|
+
let currentNode = this.first
|
|
138
|
+
while (currentNode !== null && currentNode !== node) {
|
|
139
|
+
prevNode = currentNode
|
|
140
|
+
currentNode = currentNode.next
|
|
141
|
+
}
|
|
142
|
+
if (currentNode === null) {
|
|
143
|
+
throw new Error('The reference node is not in this list.')
|
|
144
|
+
}
|
|
145
|
+
newNode.next = node
|
|
146
|
+
if (prevNode) {
|
|
147
|
+
prevNode.next = newNode
|
|
148
|
+
} else {
|
|
149
|
+
this.innerList = newNode
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (this.countCache !== null) {
|
|
153
|
+
++this.countCache
|
|
138
154
|
}
|
|
139
155
|
return this
|
|
140
156
|
}
|
|
@@ -183,9 +199,37 @@ class LinkedList {
|
|
|
183
199
|
} else {
|
|
184
200
|
this.innerList = node.next
|
|
185
201
|
}
|
|
202
|
+
if (this.tailCache === node) {
|
|
203
|
+
this.tailCache = prevNode
|
|
204
|
+
}
|
|
205
|
+
if (this.innerList === null) {
|
|
206
|
+
this.tailCache = null
|
|
207
|
+
}
|
|
208
|
+
if (this.countCache !== null) {
|
|
209
|
+
--this.countCache
|
|
210
|
+
}
|
|
186
211
|
return node
|
|
187
212
|
}
|
|
188
213
|
|
|
214
|
+
/**
|
|
215
|
+
* Refresh the remembered end and length of the list by walking it once. The list's own methods keep these up to date,
|
|
216
|
+
* so this is only needed after linkers were changed directly (for example by setting next on a linker).
|
|
217
|
+
* @return {Linker|null} The first linker of the list
|
|
218
|
+
*/
|
|
219
|
+
reset () {
|
|
220
|
+
let count = 0
|
|
221
|
+
let tail = null
|
|
222
|
+
let current = this.innerList
|
|
223
|
+
while (current !== null) {
|
|
224
|
+
++count
|
|
225
|
+
tail = current
|
|
226
|
+
current = current.next
|
|
227
|
+
}
|
|
228
|
+
this.countCache = count
|
|
229
|
+
this.tailCache = tail
|
|
230
|
+
return this.innerList
|
|
231
|
+
}
|
|
232
|
+
|
|
189
233
|
/**
|
|
190
234
|
* Retrieve a Linker item from this list by numeric index, otherwise return null.
|
|
191
235
|
* @param {number} index The integer number for retrieving a node by position.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.LinkedList=void 0;var _Linker=require("./Linker"),_LinkerIterator=require("../../recipes/LinkerIterator"),_Arrayable=require("../arrayable/Arrayable");class LinkedList{constructor(t=_Linker.Linker){this.classType=LinkedList,this.innerList=null,this.initialized=!1,this.linkerClass=t}initialize(t){return _Arrayable.Arrayable.prototype.initialize.call(this,t)}get list(){return this.innerList}get first(){return this.innerList}get last(){
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.LinkedList=void 0;var _Linker=require("./Linker"),_LinkerIterator=require("../../recipes/LinkerIterator"),_Arrayable=require("../arrayable/Arrayable");class LinkedList{constructor(t=_Linker.Linker){this.classType=LinkedList,this.innerList=null,this.initialized=!1,this.tailCache=null,this.countCache=null,this.linkerClass=t}initialize(t){return _Arrayable.Arrayable.prototype.initialize.call(this,t)}get list(){return this.innerList}get first(){return this.innerList}get last(){if(null===this.innerList)return null;let t=null!==this.tailCache?this.tailCache:this.innerList;for(;null!==t.next;)t=t.next;return this.tailCache=t,t}get length(){return null===this.countCache&&this.reset(),this.countCache}insertAfter(t,e){return e=this.linkerClass.make(e,this.linkerClass),null==t?(e.next=this.innerList,null===this.innerList&&(this.tailCache=e),this.innerList=e):(e.next=t.next,t.next=e,null===e.next&&(this.tailCache=e)),null!==this.countCache&&++this.countCache,this}insertBefore(t,e){if(e=this.linkerClass.make(e,this.linkerClass),null==t){const t=this.last;e.next=null,null===t?this.innerList=e:t.next=e,this.tailCache=e}else{let i=null,n=this.first;for(;null!==n&&n!==t;)i=n,n=n.next;if(null===n)throw new Error("The reference node is not in this list.");e.next=t,i?i.next=e:this.innerList=e}return null!==this.countCache&&++this.countCache,this}append(t,e=this.last){return this.insertAfter(e,t)}prepend(t,e=this.first){return this.insertBefore(e,t)}remove(t){if(null==t)return null;let e=null,i=this.first;for(;null!==i&&i!==t;)e=i,i=i.next;return null===i?null:(e?e.next=t.next:this.innerList=t.next,this.tailCache===t&&(this.tailCache=e),null===this.innerList&&(this.tailCache=null),null!==this.countCache&&--this.countCache,t)}reset(){let t=0,e=null,i=this.innerList;for(;null!==i;)++t,e=i,i=i.next;return this.countCache=t,this.tailCache=e,this.innerList}item(t){if(t>=0){let e=this.first,i=-1;for(;++i<t&&null!==e;)e=e.next;return i===t?e:null}let e=this.first,i=0;const n=this.length+t;if(n<0)return null;for(;i<n&&null!==e;)e=e.next,++i;return i===n?e:null}forEach(t,e=this){let i=0,n=e.first;for(;null!==n;)t(n,i,e),n=n.next,++i;return e}[Symbol.iterator](){return new _LinkerIterator.LinkerIterator(this.first)}}exports.LinkedList=LinkedList,LinkedList.fromArray=(t=[],e=_Linker.Linker,i=LinkedList)=>new i(e).initialize(e.fromArray(t).head);
|
|
@@ -21,6 +21,10 @@ export declare class LinkedTreeList implements IsTree, Iterable<TreeLinker> {
|
|
|
21
21
|
initialized: boolean;
|
|
22
22
|
/** The class used to wrap the data given to this list as tree linkers. */
|
|
23
23
|
linkerClass: typeof TreeLinker;
|
|
24
|
+
/** The last linker, remembered so that adding to the end does not need to walk the whole list (null when not known yet). */
|
|
25
|
+
private tailCache;
|
|
26
|
+
/** The number of linkers, kept up to date by the list's own methods so that the length does not need to walk the whole list (null when not known yet). */
|
|
27
|
+
private countCache;
|
|
24
28
|
/**
|
|
25
29
|
* Create the new LinkedTreeList instance, configure the list class.
|
|
26
30
|
* @param {TreeLinker} [linkerClass=TreeLinker] The class used to wrap given data as tree linkers.
|
|
@@ -43,12 +47,13 @@ export declare class LinkedTreeList implements IsTree, Iterable<TreeLinker> {
|
|
|
43
47
|
*/
|
|
44
48
|
get first(): TreeLinker;
|
|
45
49
|
/**
|
|
46
|
-
* Retrieve the last TreeLinker in the list.
|
|
50
|
+
* Retrieve the last TreeLinker in the list. The end is remembered, so this does not walk the list.
|
|
47
51
|
* @returns {TreeLinker}
|
|
48
52
|
*/
|
|
49
53
|
get last(): TreeLinker;
|
|
50
54
|
/**
|
|
51
|
-
* Return the length of the list.
|
|
55
|
+
* Return the length of the list. It is kept up to date by the list's own methods, so this does not walk the list
|
|
56
|
+
* (call reset() after linkers were changed directly).
|
|
52
57
|
* @returns {number}
|
|
53
58
|
*/
|
|
54
59
|
get length(): number;
|
|
@@ -108,7 +113,8 @@ export declare class LinkedTreeList implements IsTree, Iterable<TreeLinker> {
|
|
|
108
113
|
*/
|
|
109
114
|
remove(node: TreeLinker): TreeLinker;
|
|
110
115
|
/**
|
|
111
|
-
* Refresh all references and return head
|
|
116
|
+
* Refresh all references (the head, the end and the length) by walking the list once, and return the head. The
|
|
117
|
+
* list's own methods keep these up to date, so this is only needed after linkers were changed directly.
|
|
112
118
|
* @return {TreeLinker}
|
|
113
119
|
*/
|
|
114
120
|
reset(): TreeLinker;
|