diff --git a/codes/swift/Package.swift b/codes/swift/Package.swift index d9368354b..4cf3601c7 100644 --- a/codes/swift/Package.swift +++ b/codes/swift/Package.swift @@ -10,6 +10,7 @@ let package = Package( .executable(name: "space_complexity", targets: ["space_complexity"]), .executable(name: "leetcode_two_sum", targets: ["leetcode_two_sum"]), .executable(name: "array", targets: ["array"]), + .executable(name: "linked_list", targets: ["linked_list"]), ], targets: [ .target(name: "utils", path: "utils"), @@ -18,5 +19,6 @@ let package = Package( .executableTarget(name: "space_complexity", dependencies: ["utils"], path: "chapter_computational_complexity", sources: ["space_complexity.swift"]), .executableTarget(name: "leetcode_two_sum", path: "chapter_computational_complexity", sources: ["leetcode_two_sum.swift"]), .executableTarget(name: "array", path: "chapter_array_and_linkedlist", sources: ["array.swift"]), + .executableTarget(name: "linked_list", dependencies: ["utils"], path: "chapter_array_and_linkedlist", sources: ["linked_list.swift"]), ] ) diff --git a/codes/swift/chapter_array_and_linkedlist/linked_list.swift b/codes/swift/chapter_array_and_linkedlist/linked_list.swift new file mode 100644 index 000000000..06837f750 --- /dev/null +++ b/codes/swift/chapter_array_and_linkedlist/linked_list.swift @@ -0,0 +1,91 @@ +/** + * File: linked_list.swift + * Created Time: 2023-01-08 + * Author: nuomi1 (nuomi1@qq.com) + */ + +import utils + +/* 在链表的结点 n0 之后插入结点 P */ +func insert(n0: ListNode, P: ListNode) { + let n1 = n0.next + n0.next = P + P.next = n1 +} + +/* 删除链表的结点 n0 之后的首个结点 */ +func remove(n0: ListNode) { + if n0.next == nil { + return + } + // n0 -> P -> n1 + let P = n0.next + let n1 = P?.next + n0.next = n1 + P?.next = nil +} + +/* 访问链表中索引为 index 的结点 */ +func access(head: ListNode, index: Int) -> ListNode? { + var head: ListNode? = head + for _ in 0 ..< index { + head = head?.next + if head == nil { + return nil + } + } + return head +} + +/* 在链表中查找值为 target 的首个结点 */ +func find(head: ListNode, target: Int) -> Int { + var head: ListNode? = head + var index = 0 + while head != nil { + if head?.val == target { + return index + } + head = head?.next + index += 1 + } + return -1 +} + +@main +enum LinkedList { + /* Driver Code */ + static func main() { + /* 初始化链表 */ + // 初始化各个结点 + let n0 = ListNode(x: 1) + let n1 = ListNode(x: 3) + let n2 = ListNode(x: 2) + let n3 = ListNode(x: 5) + let n4 = ListNode(x: 4) + // 构建引用指向 + n0.next = n1 + n1.next = n2 + n2.next = n3 + n3.next = n4 + print("初始化的链表为") + PrintUtil.printLinkedList(head: n0) + + /* 插入结点 */ + insert(n0: n0, P: ListNode(x: 0)) + print("插入结点后的链表为") + PrintUtil.printLinkedList(head: n0) + + /* 删除结点 */ + remove(n0: n0) + print("删除结点后的链表为") + PrintUtil.printLinkedList(head: n0) + + /* 访问结点 */ + let node = access(head: n0, index: 3) + print("链表中索引 3 处的结点的值 = \(node!.val)") + + /* 查找结点 */ + let index = find(head: n0, target: 2) + print("链表中值为 2 的结点的索引 = \(index)") + } +} diff --git a/codes/swift/utils/PrintUtil.swift b/codes/swift/utils/PrintUtil.swift index f2b54693d..cbeab1225 100644 --- a/codes/swift/utils/PrintUtil.swift +++ b/codes/swift/utils/PrintUtil.swift @@ -15,6 +15,16 @@ public enum PrintUtil { } } + public static func printLinkedList(head: ListNode) { + var head: ListNode? = head + var list: [String] = [] + while head != nil { + list.append("\(head!.val)") + head = head?.next + } + print(list.joined(separator: " -> ")) + } + public static func printTree(root: TreeNode?) { printTree(root: root, prev: nil, isLeft: false) } diff --git a/docs/chapter_array_and_linkedlist/linked_list.md b/docs/chapter_array_and_linkedlist/linked_list.md index aa9c93ec7..7aa2754ca 100644 --- a/docs/chapter_array_and_linkedlist/linked_list.md +++ b/docs/chapter_array_and_linkedlist/linked_list.md @@ -115,7 +115,15 @@ comments: true === "Swift" ```swift title="" + /* 链表结点类 */ + class ListNode { + var val: Int // 结点值 + var next: ListNode? // 指向下一结点的指针(引用) + init(x: Int) { // 构造函数 + val = x + } + } ``` **尾结点指向什么?** 我们一般将链表的最后一个结点称为「尾结点」,其指向的是「空」,在 Java / C++ / Python 中分别记为 `null` / `nullptr` / `None` 。在不引起歧义下,本书都使用 `null` 来表示空。 @@ -255,7 +263,18 @@ comments: true === "Swift" ```swift title="linked_list.swift" - + /* 初始化链表 1 -> 3 -> 2 -> 5 -> 4 */ + // 初始化各个结点 + let n0 = ListNode(x: 1) + let n1 = ListNode(x: 3) + let n2 = ListNode(x: 2) + let n3 = ListNode(x: 5) + let n4 = ListNode(x: 4) + // 构建引用指向 + n0.next = n1 + n1.next = n2 + n2.next = n3 + n3.next = n4 ``` ## 链表优点 @@ -425,7 +444,24 @@ comments: true === "Swift" ```swift title="linked_list.swift" + /* 在链表的结点 n0 之后插入结点 P */ + func insert(n0: ListNode, P: ListNode) { + let n1 = n0.next + n0.next = P + P.next = n1 + } + /* 删除链表的结点 n0 之后的首个结点 */ + func remove(n0: ListNode) { + if n0.next == nil { + return + } + // n0 -> P -> n1 + let P = n0.next + let n1 = P?.next + n0.next = n1 + P?.next = nil + } ``` ## 链表缺点 @@ -541,7 +577,17 @@ comments: true === "Swift" ```swift title="linked_list.swift" - + /* 访问链表中索引为 index 的结点 */ + func access(head: ListNode, index: Int) -> ListNode? { + var head: ListNode? = head + for _ in 0 ..< index { + head = head?.next + if head == nil { + return nil + } + } + return head + } ``` **链表的内存占用多**。链表以结点为单位,每个结点除了保存值外,还需额外保存指针(引用)。这意味着同样数据量下,链表比数组需要占用更多内存空间。 @@ -674,7 +720,19 @@ comments: true === "Swift" ```swift title="linked_list.swift" - + /* 在链表中查找值为 target 的首个结点 */ + func find(head: ListNode, target: Int) -> Int { + var head: ListNode? = head + var index = 0 + while head != nil { + if head?.val == target { + return index + } + head = head?.next + index += 1 + } + return -1 + } ``` ## 常见链表类型 @@ -793,7 +851,16 @@ comments: true === "Swift" ```swift title="" + /* 双向链表结点类 */ + class ListNode { + var val: Int // 结点值 + var next: ListNode? // 指向后继结点的指针(引用) + var prev: ListNode? // 指向前驱结点的指针(引用) + init(x: Int) { // 构造函数 + val = x + } + } ``` ![linkedlist_common_types](linked_list.assets/linkedlist_common_types.png)