-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsinglist.js
128 lines (104 loc) · 2.62 KB
/
singlist.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/// singly linked list
export default class SingList {
// private fields
// root and length
#root
#length
// API
constructor(data) {
this.#root = new SingNode();
if ( Array.isArray(data) ) {
data = data.slice(0);
data.reverse();
for( const thing of data ) {
this.head = new SingNode(thing);
}
}
}
get head() {
return this.#root.next;
}
set head(node) {
const oldHead = this.#root.next;
if ( node !== oldHead ) {
this.#root.next = node;
// if it's not the head already, and it doesn't have a next,
// we assume it is not in the list so add 1 to length
// but this doesn't prevent cycles forming.
// could add that with a list self reference inside each node
// node.list = this; and check first
if ( node.next === undefined ) {
this.#length += 1;
}
node.next = oldHead;
}
}
reverse() {
let node = this.#root;
let nextNode = node.next;
let lastNode;
while(nextNode) {
// next node in forward direction becomes current node
node = nextNode
// its next node in forward direction becomes next current node
nextNode = node.next;
// set the current node's next to the previous node in forward direction (reversal step)
node.next = lastNode;
// save the last node to be the current node (so the next node can point back to it)
lastNode = node;
}
this.#root.next = node;
}
recursiveReverse() {
return this.#recursiveReverse(undefined, this.head);
}
#recursiveReverse(lastNode, node) {
const nextNode = node.next;
node.next = lastNode;
if ( nextNode === undefined ) {
this.#root.next = node;
return node;
}
return this.#recursiveReverse(node, nextNode);
}
get [Symbol.iterator]() {
return iterator.bind(this);
function *iterator() {
let node = this.#root;
while(node.next) {
node = node.next;
yield node.thing;
}
}
}
get length() {
return this.#length;
}
static get Node() {
return SingNode;
}
}
export const Class = SingList;
export function create(...args) {
return new SingList(...args);
}
class SingNode {
#next
#thing
constructor(thing) {
this.#thing = thing;
this.#next = null;
}
get next() {
return this.#next;
}
set next(node) {
this.#next = node;
}
get thing() {
return this.#thing;
}
set thing(thing) {
this.#thing = thing;
}
}