Skip to content

Instantly share code, notes, and snippets.

@lamprosg
Last active September 10, 2019 10:22
Show Gist options
  • Select an option

  • Save lamprosg/fe65dddf5322a2daa82ebe70fc300f21 to your computer and use it in GitHub Desktop.

Select an option

Save lamprosg/fe65dddf5322a2daa82ebe70fc300f21 to your computer and use it in GitHub Desktop.
Creating a linked list
//https://swiftbysundell.com/articles/picking-the-right-data-structure-in-swift/
/*
A list struct, which will keep track of the first and last nodes within our list
Both of those properties are read-only outside of our type, to be able to ensure data consistency
*/
struct List<Value> {
private(set) var firstNode: Node?
private(set) var lastNode: Node?
}
/*
Node type is a class,
since we want to be able to refer to nodes by reference, rather than by value
*/
extension List {
class Node {
var value: Value
fileprivate(set) weak var previous: Node? //Weak to avoid retain cycles
fileprivate(set) var next: Node?
init(value: Value) {
self.value = value
}
}
}
/*
We also want to be able to iterate over it and mutate its contents.
Let’s start with iterations which,
can easily be implemented by conforming to Sequence and implementing the makeIterator method
*/
//https://developer.apple.com/documentation/swift/sequence
extension List: Sequence {
func makeIterator() -> AnyIterator<Value> {
var node = firstNode
return AnyIterator {
// Iterate through all of our nodes by continuously
// moving to the next one and extract its value:
let value = node?.value
node = node?.next
return value
}
}
}
//Mutations
/*
Insertions.
We’ll extend List with an append method,
which adds a new node for the inserted value, and then returns that node
*/
extension List {
@discardableResult
mutating func append(_ value: Value) -> Node {
let node = Node(value: value)
node.previous = lastNode
lastNode?.next = node
lastNode = node
if firstNode == nil {
firstNode = node
}
return node
}
}
//Remove
extension List {
mutating func remove(_ node: Node) {
node.previous?.next = node.next
node.next?.previous = node.previous
// Using "triple-equals" we can compare two class
// instances by identity, rather than by value:
if firstNode === node {
firstNode = node.next
}
if lastNode === node {
lastNode = node.previous
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment