public class Node<T> {
public var value: T
public var next: Node<T>?
public var prev: Node<T>?
public init(value: T, next = Node? = nil, prev: Node? = nil) {
self.value = value
self.next = next
self.prev = prev
}
}
extension Node: CustomStringConvertible {
public var description: String {
String(describing: value)
}
}
public class DoublyLinkedList<T> {
private var head: Node<T>?
private var tail: Node<T>?
public init() { }
public var isEmpty: Bool {
head == nil
}
public var first: Node<T>? {
head
}
public func node(at index: Int) -> Node<T>? {
var currentIndex = 0
var currentNode = head
while currentNode != nil && currentIndex < index {
currentNode = currentNode!.next
currentIndex += 1
}
return currentNode
}
public func push(_ value: T) {
let newNode = Node(value: value)
guard tail != nil else {
haed = newNode
tail = newNode
return
}
newNode.next = head
head?.prev = newNode
head = newNode
}
public func append(_ value: T) {
let newNode = Node(value: value)
guard let tailNode = tail else {
push(value)
return
}
newNode.prev = tailNode
tailNode.next = newNode
tail = newNode
}
public func insert(_ value: T, after node: Node<T>) {
let newNode = Node(value: value, next: node.next, prev: node)
node.next?.prev = newNode
node.next = newNode
}
public func removeFirst() -> T? {
if isEmpty {
return nil
}
let nextNode = head?.next
defer {
nextNode?.prev = nil
head?.next = nil
head = nextNode
}
return head!.value
}
public func removeLast() -> T? {
if isEmpty {
return nil
}
let prevNode = tail?.prev
defer {
prevNode?.next = nil
tail?.prev = nil
tail = prevNode
}
return tail!.value
}
public func remove(_ node: Node<T>) -> T {
let prev = node.prev
let next = node.next
if let prev = prev {
prev.next = next
} else {
head = next
}
next?.prev = prev
if next == nil {
tail = prev
}
node.prev = nil
node.next = nil
return node.value
}
}
extension DoublyLinkedList: CustomStringConvertible {
public var description: String {
var string = ""
var current = head
while let node = current {
string.append("\(node.value) -> ")
current = node.next
}
return string + "end!"
}
}
extension DoublyLinkedList: Collection {
public struct Index: Comparable {
public var node: Node<T>?
public static func == (lhs: Index, rhs: Index) -> Bool {
switch (lhs.node, rhs.node) {
case let (left?, right?) :
return left.next === right.next
case (nil,nil):
return true
default:
return false
}
}
public static func < (lhs: Index, rhs: Index) -> Bool {
guard lhs != rhs else { return false }
let nodes = sequence(first: lhs.node) { $0?.next }
return nodes.contains { $0 === rhs.node }
}
}
public var startIndex: Index {
Index(node: head)
}
public var endIndex: Index {
Index(node: tail?.next)
}
public func index(after i: Index) -> Index {
Index(node: i.node?.next)
}
public subscript(position: Index) -> T {
position.node!.value
}
}
var doubly = DoublyLinkedList<Int>() // end!
doubly.removeFirst() // nil
doubly.append(5) // 5 -> end!
doubly.append(3) // 5 -> 3 -> end!
doubly.append(2) // 5 -> 3 -> 2-> end!
doubly.removeFirst() // 5
doubly // 3 -> 2-> end!
doubly.insert(1, after: doubly.node(at: 0)!) // 3 -> 1 -> 2 -> end!
doubly.append(6) // 3 -> 1 -> 2 -> 6 -> end!
doubly.removeLast() // 6
doubly // 3 -> 1 -> 2 -> end!
doubly.remove(doubly.node(at: 2)!) // 2
doubly // 3 -> 1 -> end!
doubly.count // 2
제가 학습한 내용을 요약하여 정리한 것입니다. 내용에 오류가 있을 수 있으며, 어떠한 피드백도 감사히 받겠습니다.
감사합니다.