Skip to content

Commit ec6d34d

Browse files
committed
Fixed LinkedList as follows:
* Modified node(atIndex:) method not to return nil, and code refactoring. * Deleted nodesBeforeAndAfter(index:) method, and modified insert methods.
1 parent 0c2aa34 commit ec6d34d

File tree

3 files changed

+166
-180
lines changed

3 files changed

+166
-180
lines changed

Linked List/LinkedList.playground/Contents.swift

Lines changed: 88 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -42,54 +42,58 @@ public final class LinkedList<T> {
4242

4343
/// Computed property to iterate through the linked list and return the last node in the list (if any)
4444
public var last: Node? {
45-
if var node = head {
46-
while case let next? = node.next {
47-
node = next
48-
}
49-
return node
50-
} else {
45+
guard let head = head else {
5146
return nil
5247
}
48+
var node = head
49+
while let next = node.next {
50+
node = next
51+
}
52+
return node
5353
}
5454

5555
/// Computed property to iterate through the linked list and return the total number of nodes
5656
public var count: Int {
57-
if var node = head {
58-
var c = 1
59-
while case let next? = node.next {
60-
node = next
61-
c += 1
62-
}
63-
return c
64-
} else {
57+
guard let head = head else {
6558
return 0
6659
}
60+
var node = head
61+
var count = 1
62+
while let next = node.next {
63+
node = next
64+
count += 1
65+
}
66+
return count
6767
}
6868

6969
/// Function to return the node at a specific index. Crashes if index is out of bounds (0...self.count)
7070
///
7171
/// - Parameter index: Integer value of the node's index to be returned
7272
/// - Returns: Optional LinkedListNode
73-
public func node(atIndex index: Int) -> Node? {
74-
if index >= 0 {
75-
var node = head
76-
var i = index
77-
while node != nil {
78-
if i == 0 { return node }
79-
i -= 1
80-
node = node!.next
81-
}
73+
public func node(atIndex index: Int) -> Node {
74+
assert(head != nil, "List is empty")
75+
if index == 0 {
76+
return head!
77+
} else {
78+
var node = head!.next
79+
for _ in 1..<index {
80+
node = node?.next
81+
if node == nil {
82+
break
83+
}
84+
}
85+
86+
assert(node != nil, "index is out of bounds.")
87+
return node!
8288
}
83-
return nil
8489
}
8590

8691
/// Subscript function to return the node at a specific index
8792
///
8893
/// - Parameter index: Integer value of the requested value's index
8994
public subscript(index: Int) -> T {
9095
let node = self.node(atIndex: index)
91-
assert(node != nil)
92-
return node!.value
96+
return node.value
9397
}
9498

9599
/// Append a value to the end of the list
@@ -104,7 +108,7 @@ public final class LinkedList<T> {
104108
///
105109
/// - Parameter node: The node containing the value to be appended
106110
public func append(_ node: Node) {
107-
let newNode = LinkedListNode(value: node.value)
111+
let newNode = node
108112
if let lastNode = last {
109113
newNode.previous = lastNode
110114
lastNode.next = newNode
@@ -124,27 +128,6 @@ public final class LinkedList<T> {
124128
}
125129
}
126130

127-
/// A private helper funciton to find the nodes before and after a specified index. Crashes if index is out of bounds (0...self.count)
128-
///
129-
/// - Parameter index: Integer value of the index between the nodes.
130-
/// - Returns: A tuple of 2 nodes before & after the specified index respectively.
131-
private func nodesBeforeAndAfter(index: Int) -> (Node?, Node?) {
132-
assert(index >= 0)
133-
134-
var i = index
135-
var next = head
136-
var prev: Node?
137-
138-
while next != nil && i > 0 {
139-
i -= 1
140-
prev = next
141-
next = next!.next
142-
}
143-
assert(i == 0) // if > 0, then specified index was too large
144-
145-
return (prev, next)
146-
}
147-
148131
/// Insert a value at a specific index. Crashes if index is out of bounds (0...self.count)
149132
///
150133
/// - Parameters:
@@ -161,41 +144,42 @@ public final class LinkedList<T> {
161144
/// - node: The node containing the value to be inserted
162145
/// - index: Integer value of the index to be inserted at
163146
public func insert(_ node: Node, atIndex index: Int) {
164-
let (prev, next) = nodesBeforeAndAfter(index: index)
165147
let newNode = LinkedListNode(value: node.value)
166-
newNode.previous = prev
167-
newNode.next = next
168-
prev?.next = newNode
169-
next?.previous = newNode
170-
171-
if prev == nil {
148+
if index == 0 {
149+
newNode.next = head
150+
head?.previous = newNode
172151
head = newNode
152+
} else {
153+
let separator = self.node(atIndex: index-1)
154+
newNode.previous = separator
155+
newNode.next = separator.next
156+
separator.next?.previous = newNode
157+
separator.next = newNode
173158
}
174159
}
175-
160+
176161
/// Insert a copy of a LinkedList at a specific index. Crashes if index is out of bounds (0...self.count)
177162
///
178163
/// - Parameters:
179164
/// - list: The LinkedList to be copied and inserted
180165
/// - index: Integer value of the index to be inserted at
181166
public func insert(_ list: LinkedList, atIndex index: Int) {
182167
if list.isEmpty { return }
183-
var (prev, next) = nodesBeforeAndAfter(index: index)
184-
var nodeToCopy = list.head
185-
var newNode: Node?
186-
while let node = nodeToCopy {
187-
newNode = Node(value: node.value)
188-
newNode?.previous = prev
189-
if let previous = prev {
190-
previous.next = newNode
191-
} else {
192-
self.head = newNode
193-
}
194-
nodeToCopy = nodeToCopy?.next
195-
prev = newNode
168+
169+
if index == 0 {
170+
let temp = head
171+
head = list.head
172+
list.last?.next = temp
173+
} else {
174+
let separate = self.node(atIndex: index-1)
175+
let temp = separate.next
176+
177+
separate.next = list.head
178+
list.head?.previous = separate
179+
180+
list.last?.next = temp
181+
temp?.previous = list.last?.next
196182
}
197-
prev?.next = next
198-
next?.previous = prev
199183
}
200184

201185
/// Function to remove all nodes/value from the list
@@ -237,8 +221,7 @@ public final class LinkedList<T> {
237221
/// - Returns: The data value contained in the deleted node
238222
@discardableResult public func remove(atIndex index: Int) -> T {
239223
let node = self.node(atIndex: index)
240-
assert(node != nil)
241-
return remove(node: node!)
224+
return remove(node: node)
242225
}
243226
}
244227

@@ -324,7 +307,7 @@ list.first // nil
324307
list.last // nil
325308

326309
list.append("Hello")
327-
list.isEmpty
310+
list.isEmpty // false
328311
list.first!.value // "Hello"
329312
list.last!.value // "Hello"
330313
list.count // 1
@@ -339,9 +322,9 @@ list.first!.next!.value // "World"
339322
list.last!.previous!.value // "Hello"
340323
list.last!.next // nil
341324

342-
list.node(atIndex: 0)!.value // "Hello"
343-
list.node(atIndex: 1)!.value // "World"
344-
list.node(atIndex: 2) // nil
325+
list.node(atIndex: 0).value // "Hello"
326+
list.node(atIndex: 1).value // "World"
327+
//list.node(atIndex: 2) // crash!
345328

346329
list[0] // "Hello"
347330
list[1] // "World"
@@ -364,25 +347,49 @@ print(list)
364347

365348
list.reverse() // [World, Swift, Hello]
366349

367-
list.node(atIndex: 0)!.value = "Universe"
368-
list.node(atIndex: 1)!.value = "Swifty"
369-
let m = list.map { s in s.characters.count }
350+
list.node(atIndex: 0).value = "Universe"
351+
list.node(atIndex: 1).value = "Swifty"
352+
let m = list.map { s in s.count }
370353
m // [8, 6, 5]
371-
let f = list.filter { s in s.characters.count > 5 }
354+
let f = list.filter { s in s.count > 5 }
372355
f // [Universe, Swifty]
373356

374357
list.remove(node: list.first!) // "Universe"
375358
list.count // 2
376359
list[0] // "Swifty"
377360
list[1] // "Hello"
378361

362+
list.count // 2
379363
list.removeLast() // "Hello"
364+
list.head?.value
380365
list.count // 1
381366
list[0] // "Swifty"
382367

383368
list.remove(atIndex: 0) // "Swifty"
384369
list.count // 0
385370

371+
let list3 = LinkedList<String>()
372+
list3.insert("2", atIndex: 0) // [2]
373+
list3.count // 1
374+
list3.insert("4", atIndex: 1) // [2,4]
375+
list3.count // 2
376+
list3.insert("5", atIndex: 2) // [2,4,5]
377+
list3.count // 3
378+
list3.insert("3", atIndex: 1) // [2,3,4,5]
379+
list3.insert("1", atIndex: 0) // [1,2,3,4,5]
380+
381+
let list4 = LinkedList<String>()
382+
list4.insert(list3, atIndex: 0) // [1,2,3,4,5]
383+
list4.count // 5
384+
385+
let list5 = LinkedList<String>()
386+
list5.append("0") // [0]
387+
list5.insert("End", atIndex:1) // [0,End]
388+
list5.count // 2
389+
list5.insert(list4, atIndex: 1) // [0,1,2,3,4,5,End]
390+
list5.count // 7
391+
392+
386393
let linkedList: LinkedList<Int> = [1, 2, 3, 4] // [1, 2, 3, 4]
387394
linkedList.count // 4
388395
linkedList[0] // 1

0 commit comments

Comments
 (0)