Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit c9e1ddb

Browse files
changing linked list types module to functional programming
1 parent 39ed6e0 commit c9e1ddb

File tree

11 files changed

+273
-542
lines changed

11 files changed

+273
-542
lines changed
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
(function (exports) {
2-
const {linked} = require('./linked.proto.module')
3-
4-
Object.assign(exports, {linked})
2+
const linked = require('./linked')
3+
Object.assign(exports, linked)
54
}((typeof module.exports !== 'undefined') ? module.exports : window))
Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
(function (exports) {
2+
// helper functions
3+
const compose = (...fns) => data => fns.reduce((v, f) => f(v), data)
4+
5+
// makes Concatenative Inheritance
6+
const inherit = (...protos) => Object.assign({}, ...protos)
7+
8+
/**
9+
base prototype for all linked list types
10+
11+
all functions are pure functions, since they don't realy on external state
12+
and produces no side effects, since they are not mutating external objects
13+
**/
14+
const base = {
15+
node (data, ...rest) {
16+
const prev = (rest[0] === 'double') ? {prev: null} : {}
17+
return Object.assign({}, {data, next: null}, prev)
18+
},
19+
setHead (options) {
20+
let {head, data} = options
21+
Object.assign(options, {head: data})
22+
return options
23+
},
24+
setCurrent (options) {
25+
let {current, data} = options
26+
Object.assign(options, {current: data})
27+
return options
28+
},
29+
setLength (options) {
30+
let {length, data} = options
31+
length += ((data) ? 1 : -1)
32+
Object.assign(options, {length})
33+
return options
34+
},
35+
setNext (options) {
36+
let {data} = options
37+
Object.assign(options.current, {next: data})
38+
return options
39+
},
40+
findPrev (options) {
41+
let {head, data} = options
42+
let c = head
43+
while (!(c.next === null)) {
44+
if (c.next.data === data) {
45+
return c
46+
} else {
47+
c = c.next
48+
}
49+
}
50+
return false
51+
}
52+
}
53+
54+
// single-linked list prototype
55+
const single = {
56+
getState () {
57+
return this
58+
},
59+
setState (options) {
60+
Object.assign(this, options)
61+
},
62+
add (data) {
63+
// retrieves the variables and concatenate the new node to be added
64+
const options = Object.assign(this.getState(), {data: this.node(data)})
65+
const fns = (!this.head && !this.current) ? [this.setHead] : [this.setNext]
66+
// and through function composition, adds an element to the list
67+
// and the result object it's going to be re assign it to the current state
68+
compose(...fns, this.setCurrent, this.setLength, this.setState)(options)
69+
},
70+
remove (data) {
71+
// retrieves variables
72+
const options = Object.assign(this.getState(), {data})
73+
// look if there's a previous link
74+
const prev = this.findPrev(options)
75+
let values, fns
76+
if (prev && !(prev.next === null)) {
77+
// updates the corresponding values to remove the requested object
78+
values = {current: prev, data: prev.next.next}
79+
// functions need to compose to remove the object requested
80+
fns = [this.setNext, this.setState]
81+
} else {
82+
values = {data: options.head.next}
83+
fns = [this.setHead, this.setState]
84+
}
85+
compose(...fns)(Object.assign(options, values)) // removes the object
86+
this.setLength(Object.assign(options, {data: false})) // decreases the length
87+
},
88+
reverse() {
89+
let prev = null
90+
let node = this.head
91+
92+
while (node) {
93+
let save = node.next
94+
node.next = prev
95+
prev = node
96+
node = save
97+
}
98+
Object.assign(this.getState(), {head: prev})
99+
},
100+
display () {
101+
let c = this.head
102+
let show = ''
103+
while (!(c === null)) {
104+
show += `${c.data} ${(c.next !== null) ? ' -> ' : ''}`
105+
c = c.next
106+
}
107+
return show
108+
},
109+
contains (data) {
110+
let c = this.head
111+
while (!(c === null)) {
112+
if (c.data === data) {
113+
return true
114+
}
115+
c = c.next
116+
}
117+
return false
118+
}, // the next functions returns a copy of the object requested
119+
getCurrent() {
120+
return Object.assign({}, this.current)
121+
},
122+
getList() {
123+
return Object.assign({}, this.head)
124+
},
125+
size() {
126+
return this.length
127+
}
128+
}
129+
130+
// double-linked list prototype
131+
const double = {
132+
add (data) {
133+
const options = Object.assign(this.getState(), {data: this.node(data, 'double')})
134+
const fns = (!this.head && !this.current) ? [this.setHead] : [this.setNext, this.setPrev]
135+
compose(...fns, this.setCurrent, this.setLength, this.setState)(options)
136+
},
137+
remove (data) {
138+
const options = Object.assign(this.getState(), {data})
139+
let prev = this.findPrev(options)
140+
let values, fns
141+
if (prev && !(prev.next === null)) {
142+
values = {current: prev, data: prev.next.next}
143+
fns = [this.setPrev, this.setNext, this.setState]
144+
} else {
145+
values = {
146+
data: {
147+
data: options.head.next.data,
148+
next: options.head.next.next,
149+
prev: null
150+
}
151+
}
152+
fns = [this.setHead, this.setState]
153+
}
154+
compose(...fns)(Object.assign(options, values))
155+
this.setLength(Object.assign(options, {data: false}))
156+
}
157+
}
158+
159+
// circular-linked list prototype
160+
const circular = {
161+
display () {
162+
let c = this.head
163+
let show = `${c.data} ${(c.next !== this.head) ? ' -> ' : ''}`
164+
while (!(c.next === this.head)) {
165+
show += `${c.next.data} ${(c.next !== this.head) ? ' -> ' : ''}`
166+
c = c.next
167+
}
168+
return show
169+
},
170+
contains(data) {
171+
let c = this.head
172+
while (!(c.next === this.head)) {
173+
if (c.data === data) {
174+
return true
175+
}
176+
c = c.next
177+
}
178+
return false
179+
}
180+
}
181+
182+
const singleLL = () => {
183+
const variables = { head: null, current: null, length: 0 }
184+
const proto = inherit(base, single)
185+
return Object.assign(Object.create(proto), variables)
186+
}
187+
188+
const doubleLL = () => {
189+
// fn to set the prev link object in the double-linked list
190+
const setPrev = (options) => {
191+
let {current, data} = options
192+
if (data !== null) {
193+
Object.assign(options.data, {prev: current})
194+
}
195+
return options
196+
}
197+
198+
const variables = { head: null, current: null, length: 0 }
199+
// first is updated the base prototype
200+
const b = Object.assign(base, {setPrev})
201+
/*
202+
then we make an Concatenative Inheritance
203+
with the base prototype that give us the basic operations,
204+
with the single prototype that gives the linked lists interface
205+
and finally set the double prototype that overrides the needed methods
206+
*/
207+
const proto = inherit(b, single, double)
208+
/*
209+
and finally return the created prototype with its variables
210+
creating the variables in each type of linked list
211+
avoids the shared state on the prototype
212+
*/
213+
return Object.assign(Object.create(proto), variables)
214+
}
215+
216+
const circularLL = () => {
217+
const setHead = (options) => {
218+
let {data} = options
219+
Object.assign(options, {head: data})
220+
Object.assign(options.head, {next: options.head})
221+
return options
222+
}
223+
const setNext = (options) => {
224+
let {data} = options
225+
let next
226+
if(data.next === null) {
227+
Object.assign(data, {next: options.head})
228+
}
229+
Object.assign(options.current, {next: data})
230+
return options
231+
}
232+
const setPrev = (options) => {
233+
let {data} = options
234+
let next
235+
if(data === null) {
236+
Object.assign(data, {data: options.head})
237+
} else {
238+
Object.assign(data, {prev: options.current})
239+
}
240+
return options
241+
}
242+
243+
const variables = {head: null, current: null, length: 0}
244+
const b = Object.assign(base, {setHead, setNext, setPrev})
245+
const proto = inherit(b, single, double, circular)
246+
247+
return Object.assign(Object.create(proto), variables)
248+
}
249+
250+
Object.assign(exports, {singleLL, doubleLL, circularLL})
251+
252+
}((typeof module.exports !== undefined) ? module.exports : window))

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /