如何用 Swift 实现一个单链表数据结构

87 阅读2分钟

单链表是我们日常开发中经常会用到的一种数据结构,它是用节点来存储信息和指向下一个节点的指针。下面我们来看一下如何用 Swift 实现一个单链表的数据结构。

定义节点类

首先,定义一个链表节点类 ListNode,它包含节点的值以及指向下一个节点的引用。

class ListNode<T> {
    var value: T
    var next: ListNode?

    init(value: T) {
        self.value = value
        self.next = nil
    }
}

在这个 ListNode 类中:

  • value 存储节点的值。
  • next 是一个指向下一个节点的可选类型,默认情况下为 nil。

定义链表类

然后,定义一个链表类 LinkedList,用于管理链表的操作,如添加、删除和遍历节点。

class LinkedList<T> {
    private var head: ListNode<T>?

    // 检查链表是否为空
    var isEmpty: Bool {
        return head == nil
    }

    // 返回链表的第一个节点
    var first: ListNode<T>? {
        return head
    }

    // 添加元素到链表的尾部
    func append(value: T) {
        let newNode = ListNode(value: value)
        if let lastNode = getLastNode() {
            lastNode.next = newNode
        } else {
            head = newNode
        }
    }

    // 获取链表的最后一个节点
    private func getLastNode() -> ListNode<T>? {
        var node = head
        while node?.next != nil {
            node = node?.next
        }
        return node
    }

    // 删除指定值的节点
    func remove(value: T) {
        var previousNode: ListNode<T>?
        var currentNode = head

        while currentNode != nil {
            if currentNode?.value == value {
                if previousNode == nil {
                    // 如果要删除的是头节点
                    head = currentNode?.next
                } else {
                    // 让前一个节点指向当前节点的下一个节点
                    previousNode?.next = currentNode?.next
                }
                break
            }
            previousNode = currentNode
            currentNode = currentNode?.next
        }
    }

    // 打印链表中的所有值
    func printList() {
        var node = head
        while node != nil {
            print(node!.value, terminator: " -> ")
            node = node?.next
        }
        print("nil")
    }
}

在这个 LinkedList 类中,我们定义了一些常用的链表操作接口:

  • isEmpty:检查链表是否为空。
  • first:获取链表的第一个节点。
  • append(value:):在链表的尾部添加一个新节点。
  • getLastNode():获取链表的最后一个节点,供内部使用。
  • remove(value:):删除第一个匹配给定值的节点。
  • printList():遍历链表并打印每个节点的值。

使用链表

下面是一个示例,展示如何创建链表、添加节点、删除节点并打印链表。

let list = LinkedList<Int>()
list.append(value: 1)
list.append(value: 2)
list.append(value: 3)
list.printList() // 输出: 1 -> 2 -> 3 -> nil

list.remove(value: 2)
list.printList() // 输出: 1 -> 3 -> nil