You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -110,14 +110,14 @@ Let's also add a property that gives you the last node in the list. This is wher
110
110
111
111
```swift
112
112
publicvar last: Node? {
113
-
ifvar node = head {
114
-
whilelet next = node.next {
115
-
node = next
116
-
}
117
-
return node
118
-
} else {
113
+
guardvar node = head else {
119
114
returnnil
120
115
}
116
+
117
+
whilelet next = node.next {
118
+
node = next
119
+
}
120
+
return node
121
121
}
122
122
```
123
123
@@ -198,16 +198,16 @@ Let's add a method to count how many nodes are in the list. This will look very
198
198
199
199
```swift
200
200
publicvar count: Int {
201
-
ifvar node = head {
202
-
var c =1
203
-
whilelet next = node.next {
204
-
node = next
205
-
c +=1
206
-
}
207
-
return c
208
-
} else {
201
+
guardvar node = head else {
209
202
return0
210
203
}
204
+
205
+
var count =1
206
+
whilelet next = node.next {
207
+
node = next
208
+
count +=1
209
+
}
210
+
return count
211
211
}
212
212
```
213
213
@@ -218,37 +218,43 @@ It loops through the list in the same manner but this time increments a counter
218
218
What if we wanted to find the node at a specific index in the list? With an array we can just write `array[index]` and it's an **O(1)** operation. It's a bit more involved with linked lists, but again the code follows a similar pattern:
219
219
220
220
```swift
221
-
publicfuncnodeAt(_index: Int) -> Node? {
222
-
if index >=0 {
223
-
var node = head
224
-
var i = index
225
-
while node !=nil {
226
-
if i ==0 { return node }
227
-
i -=1
228
-
node = node!.next
221
+
publicfuncnode(atIndexindex: Int) -> Node {
222
+
if index ==0 {
223
+
return head!
224
+
} else {
225
+
var node = head!.next
226
+
for_in1..<index {
227
+
node = node?.next
228
+
if node ==nil { //(*1)
229
+
break
230
+
}
229
231
}
232
+
return node!
230
233
}
231
-
returnnil
232
234
}
233
235
```
234
236
235
-
The loop looks a little different but it does the same thing: it starts at `head` and then keeps following the `node.next` pointers to step through the list. We're done when we've seen `index` nodes, i.e. when the counter has reached 0.
237
+
First we check whether the given index is 0 or not. Because if it is 0, it returns the head as it is.
238
+
However, when the given index is greater than 0, it starts at head then keeps following the node.next pointers to step through the list.
239
+
The difference from count method at this time is that there are two termination conditions.
240
+
One is when the for-loop statement reaches index, and we were able to acquire the node of the given index.
241
+
The second is when `node.next` in for-loop statement returns nil and cause break. (*1)
242
+
This means that the given index is out of bounds and it causes a crash.
236
243
237
244
Try it out:
238
245
239
246
```swift
240
247
list.nodeAt(0)!.value// "Hello"
241
248
list.nodeAt(1)!.value// "World"
242
-
list.nodeAt(2) //nil
249
+
//list.nodeAt(2) // crash
243
250
```
244
251
245
252
For fun we can implement a `subscript` method too:
246
253
247
254
```swift
248
255
publicsubscript(index: Int) -> T {
249
-
let node =nodeAt(index)
250
-
assert(node !=nil)
251
-
return node!.value
256
+
let node =node(atIndex: index)
257
+
return node.value
252
258
}
253
259
```
254
260
@@ -264,84 +270,100 @@ It crashes on `list[2]` because there is no node at that index.
264
270
265
271
So far we've written code to add new nodes to the end of the list, but that's slow because you need to find the end of the list first. (It would be fast if we used a tail pointer.) For this reason, if the order of the items in the list doesn't matter, you should insert at the front of the list instead. That's always an **O(1)** operation.
266
272
267
-
Let's write a method that lets you insert a new node at any index in the list. First, we'll define a helper function:
This returns a tuple containing the node currently at the specified index and the node that immediately precedes it, if any. The loop is very similar to `nodeAtIndex()`, except that here we also keep track of what the previous node is as we iterate through the list.
289
-
290
-
Let's look at an example. Suppose we have the following list:
291
273
292
-
head --> A --> B --> C --> D --> E --> nil
293
-
294
-
We want to find the nodes before and after index 3. As we start the loop, `i = 3`, `next` points at `"A"`, and `prev` is nil.
295
-
296
-
head --> A --> B --> C --> D --> E --> nil
297
-
next
298
-
299
-
We decrement `i`, make `prev` point to `"A"`, and move `next` to the next node, `"B"`:
300
-
301
-
head --> A --> B --> C --> D --> E --> F --> nil
302
-
prev next
303
-
304
-
Again, we decrement `i` and update the pointers. Now `prev` points to `"B"`, and `next` points to `"C"`:
305
-
306
-
head --> A --> B --> C --> D --> E --> F --> nil
307
-
prev next
308
-
309
-
As you can see, `prev` always follows one behind `next`. We do this one more time and then `i` equals 0 and we exit the loop:
310
-
311
-
head --> A --> B --> C --> D --> E --> F --> nil
312
-
prev next
313
-
314
-
The `assert()` after the loop checks whether there really were enough nodes in the list. If `i > 0` at this point, then the specified index was too large.
315
-
316
-
> **Note:** If any of the loops in this article don't make much sense to you, then draw a linked list on a piece of paper and step through the loop by hand, just like what we did here.
317
-
318
-
For this example, the function returns `("C", "D")` because `"D"` is the node at index 3 and `"C"` is the one right before that.
319
-
320
-
Now that we have this helper function, we can write the method for inserting nodes:
274
+
Let's write a method that lets you insert a new node at any index in the list.
1. First, we need to find where to insert this node. After calling the helper method, `prev` points to the previous node and `next` is the node currently at the given index. We'll insert the new node in between these two. Note that `prev` can be nil (index is 0), `next` can be nil (index equals size of the list), or both can be nil if the list is empty.
295
+
As with node(atIndex :) method, insert(_: at:) method also branches depending on whether the given index is 0 or not.
296
+
First let's look at the former case. Suppose we have the following list and the new node(C).
297
+
298
+
+---------+ +---------+
299
+
head --->| |---->| |-----//----->
300
+
| A | | B |
301
+
nil <---| |<----| |<----//------
302
+
+---------+ +---------+
303
+
[0] [1]
304
+
305
+
306
+
+---------+
307
+
new --->| |----> nil
308
+
| C |
309
+
| |
310
+
+---------+
311
+
312
+
Now put the new node before the first node. In this way:
313
+
314
+
new.next = head
315
+
head.previous = new
316
+
317
+
+---------+ +---------+ +---------+
318
+
new --->| |--> head -->| |---->| |-----//----->
319
+
| C | | A | | B |
320
+
| |<-----------| |<----| |<----//------
321
+
+---------+ +---------+ +---------+
322
+
323
+
324
+
Finally, replace the head with the new node.
325
+
326
+
head = new
327
+
328
+
+---------+ +---------+ +---------+
329
+
head --->| |--->| |---->| |-----//----->
330
+
| C | | A | | B |
331
+
nil <---| |<---| |<----| |<----//------
332
+
+---------+ +---------+ +---------+
333
+
[0] [1]
334
+
335
+
336
+
However, when the given index is greater than 0, it is necessary to get the node previous and next index and insert between them.
337
+
You can also obtain the previous and next node using node(atIndex:) as follows:
338
+
339
+
+---------+ +---------+ +---------+
340
+
head --->| |---//--->| |---->| |----
341
+
| 0 | | A | | B |
342
+
nil <---| |---//<---| |<----| |<---
343
+
+---------+ +---------+ +---------+
344
+
[index-1] [index]
345
+
^ ^
346
+
| |
347
+
prev next
348
+
349
+
prev = node(at: index-1)
350
+
next = prev.next
351
+
352
+
Now insert new node between the prev and the next.
353
+
354
+
new.prev = prev; prev.next = new // connect prev and new.
355
+
new.next = next; next.prev = new // connect new and next.
356
+
357
+
+---------+ +---------+ +---------+ +---------+
358
+
head --->| |---//--->| |---->| |---->| |
359
+
| 0 | | A | | C | | B |
360
+
nil <---| |---//<---| |<----| |<----| |
361
+
+---------+ +---------+ +---------+ +---------+
362
+
[index-1] [index] [index+1]
363
+
^ ^ ^
364
+
| | |
365
+
prev new next
341
366
342
-
2. Create the new node and connect the `previous` and `next` pointers. Because the local `prev` and `next` variables are optionals and may be nil, so we use optional chaining here.
343
-
344
-
3. If the new node is being inserted at the front of the list, we need to update the `head` pointer. (Note: If the list had a tail pointer, you'd also need to update that pointer here if `next == nil`, because that means the last element has changed.)
345
367
346
368
Try it out:
347
369
@@ -353,8 +375,7 @@ list[2] // "World"
353
375
```
354
376
355
377
Also try adding new nodes to the front and back of the list, to verify that this works properly.
356
-
357
-
> **Note:** The `nodesBeforeAndAfter()` and `insert(atIndex)` functions can also be used with a singly linked list because we don't depend on the node's `previous` pointer to find the previous element.
378
+
> **Note:** The `node(atIndex:)` and `insert(_: atIndex:)` functions can also be used with a singly linked list because we don't depend on the node's `previous` pointer to find the previous element.
358
379
359
380
What else do we need? Removing nodes, of course! First we'll do `removeAll()`, which is really simple:
0 commit comments