Swift 5.3 数据结构——链表 LinkedList

链表

链表是按线性单向顺序排列的值的集合
与数组对比,链表的优势是插入和删除时间复杂度都是O(1)

链表由一系列的节点Node组成,一个节点有两个部分,一部分保存一个数据,另一部分保存下一个节点

public class Node {
    public var value: Value
    public var next: Node?
    
    public init(value: Value, next: Node? = nil) {
        self.value = value
        self.next = next
    }
}

extension Node: CustomStringConvertible {
    public var description: String {
        guard let next = next else {
            return "\(value)"
        }
        return "\(value)=>" + String(describing: next)
    }
}

一个链表中会保存头结点和尾结点。

public struct LinkedList {
    public var head: Node?
    public var tail: Node?
    
    public init() {}
    
    public var isEmpty: Bool {
        head == nil
    }
}

双向链表中的节点Node还会保存前一个Node

public class Node {
    public var value: T
    public var next: Node?
    public var previous: Node?
    
    public init(value: T) {
        self.value = value
    }
}

链表一般会包含一下常用的增删改查方法
push 在头部增加一个node
append 在尾部增加一个node
insert 插入一个node
node at index 查询一个node
pop 移除头部的一个node
removeLast 移除尾部的一个node
remove after 移除某个node之后的一个node

extension LinkedList {
    public mutating func push(_ value: Value) {
        copyNodes()
        head = Node(value: value, next: head)
        if tail == nil {
            tail = head
        }
    }
    
    public mutating func append(_ value: Value) {
        copyNodes()
        guard !isEmpty else {
            push(value)
            return
        }
        
        tail!.next = Node(value: value)
        
        tail = tail?.next
    }
    
    @discardableResult
    public mutating func insert(_ value: Value, after node: Node) -> Node {
        copyNodes()
        guard tail !== node else {
            append(value)
            return tail!
        }
        node.next = Node(value: value, next: node.next!)
        return node.next!
    }
    
    
    public func node(at index: Int) -> Node? {
        var currentNode = head
        var currentIndex = 0
        
        while currentNode != nil && currentIndex < index {
            currentNode = currentNode!.next
            currentIndex += 1
        }
        
        return currentNode
    }
}

extension LinkedList {
    @discardableResult
    public mutating func pop() -> Value? {
        copyNodes()
        
        defer {
            head = head?.next
            if isEmpty {
                tail = nil
            }
        }
        
        return head?.value
    }
    
    @discardableResult
    public mutating func removeLast() -> Value? {
        copyNodes()
        guard let head = head else {
            return nil
        }
        
        guard head.next != nil else {
            return pop()
        }
        
        var prev = head
        var current = head
        
        while let next = current.next {
            prev = current
            current = next
        }
        
        prev.next = nil
        tail = prev
        return current.value
    }
    
    @discardableResult
    public mutating func remove(after node: Node) -> Value? {
        
        guard let node = copyNodes(returningCopyOf: node) else {
            return nil
        }
        defer {
            if node.next === tail {
                tail = node
            }
            node.next = node.next?.next
        }
        
        return node.next?.value
    }
}

因为上面的链表是struct类型,但是节点是class类型,因此在链表直接赋值传递的时候,新链表中的节点跟旧链表中的节点在内存中是一个地址,更改新链表的数据,就会影响旧链表。
这时候需要引入一个COW(copy and write),顾名思义,就是每次操作链表之前先进行一次copy,然后再执行相应的操作,这样每次操作完获得的链表都是新的,里面的节点也都是新的,旧链表会自动释放的。

 private mutating func copyNodes(returningCopyOf node: Node?) -> Node? {
        guard !isKnownUniquelyReferenced(&head) else {
            return nil
        }
        guard var oldNode = head else {
            return nil
        }
        
        head = Node(value: oldNode.value)
        var newNode = head
        var nodeCopy: Node?
        
        while let nextOldNode = oldNode.next {
            if oldNode === node {
                nodeCopy = newNode
            }
            newNode!.next = Node(value: nextOldNode.value)
            newNode = newNode!.next
            
            oldNode = nextOldNode
        }
        
        return nodeCopy
    }

github仓库地址 https://github.com/SunZhiC/DataStructuresInSwift

References

Data Structures & Algorithms in Swift by Matthijs Hollemans.
https://github.com/apple/swift-algorithms
https://github.com/raywenderlich/swift-algorithm-club

你可能感兴趣的:(Swift 5.3 数据结构——链表 LinkedList)