-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathLinkedList.js
More file actions
336 lines (293 loc) · 7.51 KB
/
LinkedList.js
File metadata and controls
336 lines (293 loc) · 7.51 KB
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
import {
eqComparer
} from '../common/toollib'
import {
LinkedListNode,
loopToFind,
} from './LinkedListNode'
/**
* @description 链表
* @author 码路工人 CoderMonkey
* @export
* @class LinkedList
*/
export class LinkedList {
/**
* 构造函数
* @param {function|null} customizedComparer 可选参数 指定比对方法
*/
constructor(customizedComparer = null) {
this.__comparator = eqComparer(customizedComparer)
this.clear()
}
/**
* 链表元素个数
*
* @readonly
* @memberof LinkedList
*/
get size() {
return this.__count
}
/**
* 是否为空链表
*
* @readonly
* @memberof LinkedList
*/
get isEmpty() {
return this.size === 0
}
/**
* 获取链表的首元素数据
* @deprecated since v0.05 change to use [head] instead
* @readonly
* @memberof LinkedList
*/
get firstNode() {
return this.findAt(0)
}
/**
* 获取链表的首元素数据
*
* @readonly
* @memberof LinkedList
*/
get head() {
return this.__head && this.__head.data
}
/**
* 获取链表的尾元素数据
* @deprecated since v0.05 change to use [tail] instead
* @readonly
* @memberof LinkedList
*/
get lastNode() {
return this.findAt(this.size - 1)
}
/**
* 获取链表的尾元素数据
*
* @readonly
* @memberof LinkedList
*/
get tail() {
return this.__tail && this.__tail.data
}
/**
* 向链表末尾添加数据
*
* @param {*} data 链表元素的数据
* @returns true
* @memberof LinkedList
*/
append(data) {
// 1.创建新元素
const newNode = new LinkedListNode(data)
// 2.1链表为空时,直接添加到末尾
if (this.isEmpty) {
this.__head = newNode
this.__tail = newNode
}
// 2.2链表非空时,末尾添加新元素
else {
this.__tail.next = newNode
this.__tail = newNode
}
// 3.内部计数加1
this.__count += 1
return true
}
/**
* 向链表指定位置插入元素
*
* @param {number} position 插入位置
* @param {*} data
* @returns 插入结果:true/false
* @memberof LinkedList
*/
insert(position, data) {
// 1.边界检查(插入位置)
if (position < 0 || position > this.__count) return false
// 2.创建新元素
var newNode = new LinkedListNode(data)
// 3.1插入到链表头部
if (position === 0) {
newNode.next = this.__head
this.__head = newNode
// 内部计数加1
this.__count += 1
}
// 3.2插入到链表尾部
else if (position === this.size) {
this.append(data)
}
// 3.3以外
else {
let previous = null
let current = this.__head
let index = 0
while (index < position) {
previous = current
current = current.next
index++
}
previous.next = newNode
newNode.next = current
// 内部计数加1
this.__count += 1
}
return true
}
/**
* 删除链表中某个元素
*
* @param {*} data 元素数据
* @returns 删除结果:true/false
* @memberof LinkedList
*/
remove(data) {
const position = this.indexOf(data)
if (position === -1) return false
return this.removeAt(position)
}
/**
* 删除链表指定位置元素
*
* @param {number} position 位置下标
* @returns 删除结果:true/false
* @memberof LinkedList
*/
removeAt(position) {
// 1.边界检查
if (position < 0 || position >= this.__count) return false
// 2.1.链表中只要一个元素的时候
if (this.size === 1) {
// position 只能是 0
this.__head = this.__tail = null
}
// 2.2.链表中有多个元素的时候
else {
let index = 0
let previous = null
let current = this.__head
// 2.2.1.找到指定位置元素
while (index++ < position) {
previous = current
current = current.next
}
// 2.2.2.使当前元素不再被引用
previous.next = current.next
// 2.2.3.删除尾元素的时候
if (this.size - 1 === position) {
// 更新 tail 的指针
this.__tail = previous
}
}
// 3.内部计数减1
this.__count -= 1
return true
}
/**
* 更新链表指定位置的元素
*
* @param {number} position 位置下标
* @param {*} data 新数据
* @returns 更新结果:true/false
* @memberof LinkedList
*/
update(position, data) {
// 1.边界检查
if (position < 0 || position >= this.__count) return false
// 2.找到指定位置元素
const current = loopToFind(position, this.__head)
// 3.修改当前元素数据
current.data = data
// 4.修改完成,返回 true
return true
}
/**
* 查看指定位置元素的数据
*
* @param {number} position 位置下标
* @returns 元素数据
* @memberof LinkedList
*/
findAt(position) {
// 1.边界检查
if (position < 0 || position >= this.__count) return undefined
// 2.找到指定位置元素
const current = loopToFind(position, this.__head)
// 3.返回该节点元素的数据部分
return current.data
}
/**
* 根据指定元素数据获取在链表中的位置下标
*
* @param {*} data 元素数据
* @returns 位置下标
* @memberof LinkedList
*/
indexOf(data) {
let index = 0
let current = this.__head
// 根据指点数据查找节点元素
while (current) {
if (this.__comparator(current.data, data)) {
return index
}
current = current.next
index += 1
}
// 没有找到符合的节点元素
return -1
}
/**
* 遍历链表
*
* @param {function} callback
* @memberof LinkedList
*/
traverse(callback) {
// 参数检查(回调函数)
if (!callback || !isFunction(callback)) return
// 起始元素设为 head
let current = this.__head
// 头部起始,向后遍历
while (current) {
callback(current.data)
current = current.next
}
}
/**
* 清空链表
*
* @memberof LinkedList
*/
clear() {
// 记录链表首尾
this.__head = null
this.__tail = null
// 记录链表元素个数
this.__count = 0
}
/**
* 获取字符串
*
* @returns 链表的字符串
* @memberof LinkedList
*/
toString() {
let str = '[HEAD] -> '
let current = this.__head
while (current) {
str += current + ' -> '
current = current.next
}
if (str === '[HEAD] -> ') {
str = '[HEAD] -> Null'
}
str += `\r\nCount: ${this.size}`
return str
}
}