Last active
September 10, 2019 10:22
-
-
Save lamprosg/fe65dddf5322a2daa82ebe70fc300f21 to your computer and use it in GitHub Desktop.
Creating a linked list
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //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