-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathDoublyLinkedList.js
More file actions
285 lines (250 loc) · 7.33 KB
/
DoublyLinkedList.js
File metadata and controls
285 lines (250 loc) · 7.33 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
import { LinkedList } from './LinkedList'
import {
isFunction,
} from '../common/toollib'
import {
LinkedListNode,
loopToFind,
needReversal,
doublyFindAt,
} from './LinkedListNode'
/**
* 双向链表
*
* @export DoublyLinkedList
* @class DoublyLinkedList
* @extends {LinkedList}
*/
export class DoublyLinkedList extends LinkedList {
constructor(customizedComparer = null) {
super(customizedComparer)
}
/**
* 向链表末尾添加数据
*
* @param {*} data 链表元素的数据
* @returns true
* @memberof DoublyLinkedList
*/
append(data) {
let newNode = new LinkedListNode(data)
// 1.判断链表是否为空
if (this.isEmpty) {
// 新元素既是首也是尾
this.__head = newNode
this.__tail = newNode
}
// 2.非空链表时,添加到尾部
else {
this.__tail.next = newNode
newNode.prev = this.__tail
this.__tail = newNode
}
// 3.计数加1
this.__count += 1
return true
}
/**
* 向链表指定位置插入元素
*
* @param {number} position 插入位置
* @param {*} data
* @returns 插入结果:true/false
* @memberof DoublyLinkedList
*/
insert(position, data) {
// 1.边界检查(插入位置)
if (position < 0 || position > this.__count) return false
let newNode = new LinkedListNode(data)
// 2.插入元素时链表为空
if (this.isEmpty) {
this.__head = newNode
this.__tail = newNode
}
// 3.链表非空
else {
// 3.1插入到链表头部
if (position === 0) {
newNode.next = this.__head
this.__head.prev = newNode
this.__head = newNode
}
// 3.2插入到链表尾部
else if (position === this.__count) {
this.__tail.next = newNode
newNode.prev = this.__tail
this.__tail = newNode
}
// 3.3以外
else {
let current = doublyFindAt(this.size, position, this.__head, this.__tail)
current.prev.next = newNode
newNode.prev = current.prev
newNode.next = current
current.prev = newNode
}
}
// 4.计数加1
this.__count += 1
return true
}
/**
* 删除链表指定位置元素
*
* @param {number} position 位置下标
* @returns 删除结果:true/false
* @memberof DoublyLinkedList
*/
removeAt(position) {
// 1.边界检查
if (position < 0 || position >= this.__count) return false
// 2.只有一个元素
if (this.size === 1) {
this.__head = null
this.__tail = null
}
// 3.多个元素的情况
else {
// 3.1 删首
if (position === 0) {
this.__head = current.next
current.next.prev = null
}
// 3.2 删尾
else if (position === this.__count - 1) {
this.__tail = this.__tail.prev
this.__tail.next = null
}
// 3.3 以外
else {
let current = doublyFindAt(this.size, position, this.__head, this.__tail)
current.prev.next = current.next
current.next.prev = current.prev
}
}
// 4.计数减1
this.__count -= 1
return true
}
/**
* 删除指定数据的元素
*
* @param {*} data 元素数据
* @returns 返回删除的元素数据
* @memberof DoublyLinkedList
*/
remove(data) {
// 1.根据指定数据取得下标值
let index = this.indexOf(data)
// 2.检查下标值是否正常取到
if (index === -1) return false
// 3.根据取到的下标,调用 removeAt 方法进行删除
return this.removeAt(index)
}
/**
* 更新指定位置元素
*
* @param {number} position 位置下标
* @param {*} data 更新的数据
* @returns 更新结果:成功true/失败false
* @memberof DoublyLinkedList
*/
update(position, data) {
// 1.边界检查
if (position < 0 || position >= this.__count) return false
// 2.找到指定下标位置元素(根据所处位置从头或从尾查找)
let targetNode = doublyFindAt(this.size, position, this.__head, this.__tail)
// 3.修改数据
targetNode.data = data
return true
}
/**
* 获取指定位置元素的数据
*
* @param {number} position 位置下标
* @returns 元素的数据
* @memberof DoublyLinkedList
*/
findAt(position) {
// 1.边界检查
if (position < 0 || position >= this.__count) return undefined
// 2.判断该位置处于链表前半部分还是后半部分
// 前半部分的时候,从 head 开始查找
// 后半部分的时候,从 tail 开始查找
const reversal = needReversal(this.size, position)
// 3.找到指定位置元素
const current = reversal ?
loopToFind(position, this.__tail, this.size - 1) :
loopToFind(position, this.__head, null)
// 4.返回该节点元素的数据部分
return current.data
}
/**
* 根据指定元素数据获取在链表中的位置下标
*
* @param {*} data
* @returns 位置下标
* @memberof DoublyLinkedList
*/
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 DoublyLinkedList
*/
backwardTraverse(callback) {
// 参数检查(回调函数)
if (!callback || !isFunction(callback)) return
// 起始元素设为 tail
let current = this.__tail
// 尾部起始,向前遍历
while (current) {
callback(current.data)
current = current.prev
}
}
/**
* 从首元素开始遍历
*
* @param {function} callback
* @memberof DoublyLinkedList
*/
forwardTraverse(callback) {
// 参数检查(回调函数)
if (!callback || !isFunction(callback)) return
// 起始元素设为 head
let current = this.__head
// 头部起始,向后遍历
while (current) {
callback(current.data)
current = current.next
}
}
/**
* 根据指定顺序,遍历双向链表
*默认为 forwardTravase
* @param {function} callback
* @param {boolean} [reversal=false]
* @memberof DoublyLinkedList
*/
traverse(callback, reversal = false) {
reversal
?
this.backwardTraverse(callback) :
this.forwardTraverse(callback)
}
}