From 1665fe176c5fee8455b4849c828e4a82d79d2578 Mon Sep 17 00:00:00 2001 From: nuomi1 Date: Mon, 30 Jan 2023 15:43:29 +0800 Subject: [PATCH] feat: add Swift codes for chapter_searching articles (#309) * feat: add Swift codes for linear_search article * feat: add Swift codes for binary_search article * feat: add Swift codes for hashing_search article --- codes/swift/Package.swift | 6 ++ .../chapter_searching/binary_search.swift | 62 +++++++++++++++++++ .../chapter_searching/hashing_search.swift | 50 +++++++++++++++ .../chapter_searching/linear_search.swift | 53 ++++++++++++++++ codes/swift/utils/ListNode.swift | 10 +++ docs/chapter_searching/binary_search.md | 45 +++++++++++++- docs/chapter_searching/hashing_search.md | 14 ++++- docs/chapter_searching/linear_search.md | 28 ++++++++- 8 files changed, 261 insertions(+), 7 deletions(-) create mode 100644 codes/swift/chapter_searching/binary_search.swift create mode 100644 codes/swift/chapter_searching/hashing_search.swift create mode 100644 codes/swift/chapter_searching/linear_search.swift diff --git a/codes/swift/Package.swift b/codes/swift/Package.swift index 31ef3b332..1e7e292e3 100644 --- a/codes/swift/Package.swift +++ b/codes/swift/Package.swift @@ -28,6 +28,9 @@ let package = Package( .executable(name: "binary_search_tree", targets: ["binary_search_tree"]), .executable(name: "avl_tree", targets: ["avl_tree"]), .executable(name: "my_heap", targets: ["my_heap"]), + .executable(name: "linear_search", targets: ["linear_search"]), + .executable(name: "binary_search", targets: ["binary_search"]), + .executable(name: "hashing_search", targets: ["hashing_search"]), ], targets: [ .target(name: "utils", path: "utils"), @@ -54,5 +57,8 @@ let package = Package( .executableTarget(name: "binary_search_tree", dependencies: ["utils"], path: "chapter_tree", sources: ["binary_search_tree.swift"]), .executableTarget(name: "avl_tree", dependencies: ["utils"], path: "chapter_tree", sources: ["avl_tree.swift"]), .executableTarget(name: "my_heap", dependencies: ["utils"], path: "chapter_heap", sources: ["my_heap.swift"]), + .executableTarget(name: "linear_search", dependencies: ["utils"], path: "chapter_searching", sources: ["linear_search.swift"]), + .executableTarget(name: "binary_search", path: "chapter_searching", sources: ["binary_search.swift"]), + .executableTarget(name: "hashing_search", dependencies: ["utils"], path: "chapter_searching", sources: ["hashing_search.swift"]), ] ) diff --git a/codes/swift/chapter_searching/binary_search.swift b/codes/swift/chapter_searching/binary_search.swift new file mode 100644 index 000000000..25930b238 --- /dev/null +++ b/codes/swift/chapter_searching/binary_search.swift @@ -0,0 +1,62 @@ +/** + * File: binary_search.swift + * Created Time: 2023-01-28 + * Author: nuomi1 (nuomi1@qq.com) + */ + +/* 二分查找(双闭区间) */ +func binarySearch(nums: [Int], target: Int) -> Int { + // 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素 + var i = 0 + var j = nums.count - 1 + // 循环,当搜索区间为空时跳出(当 i > j 时为空) + while i <= j { + let m = (i + j) / 2 // 计算中点索引 m + if nums[m] < target { // 此情况说明 target 在区间 [m+1, j] 中 + i = m + 1 + } else if nums[m] > target { // 此情况说明 target 在区间 [i, m-1] 中 + j = m - 1 + } else { // 找到目标元素,返回其索引 + return m + } + } + // 未找到目标元素,返回 -1 + return -1 +} + +/* 二分查找(左闭右开) */ +func binarySearch1(nums: [Int], target: Int) -> Int { + // 初始化左闭右开 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1 + var i = 0 + var j = nums.count + // 循环,当搜索区间为空时跳出(当 i = j 时为空) + while i < j { + let m = (i + j) / 2 // 计算中点索引 m + if nums[m] < target { // 此情况说明 target 在区间 [m+1, j) 中 + i = m + 1 + } else if nums[m] > target { // 此情况说明 target 在区间 [i, m) 中 + j = m + } else { // 找到目标元素,返回其索引 + return m + } + } + // 未找到目标元素,返回 -1 + return -1 +} + +@main +enum BinarySearch { + /* Driver Code */ + static func main() { + let target = 6 + let nums = [1, 3, 6, 8, 12, 15, 23, 67, 70, 92] + + /* 二分查找(双闭区间) */ + var index = binarySearch(nums: nums, target: target) + print("目标元素 6 的索引 = \(index)") + + /* 二分查找(左闭右开) */ + index = binarySearch1(nums: nums, target: target) + print("目标元素 6 的索引 = \(index)") + } +} diff --git a/codes/swift/chapter_searching/hashing_search.swift b/codes/swift/chapter_searching/hashing_search.swift new file mode 100644 index 000000000..1ff8a5754 --- /dev/null +++ b/codes/swift/chapter_searching/hashing_search.swift @@ -0,0 +1,50 @@ +/** + * File: hashing_search.swift + * Created Time: 2023-01-28 + * Author: nuomi1 (nuomi1@qq.com) + */ + +import utils + +/* 哈希查找(数组) */ +func hashingSearch(map: [Int: Int], target: Int) -> Int { + // 哈希表的 key: 目标元素,value: 索引 + // 若哈希表中无此 key ,返回 -1 + return map[target, default: -1] +} + +/* 哈希查找(链表) */ +func hashingSearch1(map: [Int: ListNode], target: Int) -> ListNode? { + // 哈希表的 key: 目标结点值,value: 结点对象 + // 若哈希表中无此 key ,返回 null + return map[target] +} + +@main +enum HashingSearch { + /* Driver Code */ + static func main() { + let target = 3 + + /* 哈希查找(数组) */ + let nums = [1, 5, 3, 2, 4, 7, 5, 9, 10, 8] + // 初始化哈希表 + var map: [Int: Int] = [:] + for i in nums.indices { + map[nums[i]] = i // key: 元素,value: 索引 + } + let index = hashingSearch(map: map, target: target) + print("目标元素 3 的索引 = \(index)") + + /* 哈希查找(链表) */ + var head = ListNode.arrToLinkedList(arr: nums) + // 初始化哈希表 + var map1: [Int: ListNode] = [:] + while head != nil { + map1[head!.val] = head! // key: 结点值,value: 结点 + head = head?.next + } + let node = hashingSearch1(map: map1, target: target) + print("目标结点值 3 的对应结点对象为 \(node!)") + } +} diff --git a/codes/swift/chapter_searching/linear_search.swift b/codes/swift/chapter_searching/linear_search.swift new file mode 100644 index 000000000..329c356d2 --- /dev/null +++ b/codes/swift/chapter_searching/linear_search.swift @@ -0,0 +1,53 @@ +/** + * File: linear_search.swift + * Created Time: 2023-01-28 + * Author: nuomi1 (nuomi1@qq.com) + */ + +import utils + +/* 线性查找(数组) */ +func linearSearch(nums: [Int], target: Int) -> Int { + // 遍历数组 + for i in nums.indices { + // 找到目标元素,返回其索引 + if nums[i] == target { + return i + } + } + // 未找到目标元素,返回 -1 + return -1 +} + +/* 线性查找(链表) */ +func linearSearch(head: ListNode?, target: Int) -> ListNode? { + var head = head + // 遍历链表 + while head != nil { + // 找到目标结点,返回之 + if head?.val == target { + return head + } + head = head?.next + } + // 未找到目标结点,返回 null + return nil +} + +@main +enum LinearSearch { + /* Driver Code */ + static func main() { + let target = 3 + + /* 在数组中执行线性查找 */ + let nums = [1, 5, 3, 2, 4, 7, 5, 9, 10, 8] + let index = linearSearch(nums: nums, target: target) + print("目标元素 3 的索引 = \(index)") + + /* 在链表中执行线性查找 */ + let head = ListNode.arrToLinkedList(arr: nums) + let node = linearSearch(head: head, target: target) + print("目标结点值 3 的对应结点对象为 \(node!)") + } +} diff --git a/codes/swift/utils/ListNode.swift b/codes/swift/utils/ListNode.swift index 5fa3671eb..a45d212ee 100644 --- a/codes/swift/utils/ListNode.swift +++ b/codes/swift/utils/ListNode.swift @@ -11,4 +11,14 @@ public class ListNode { public init(x: Int) { val = x } + + public static func arrToLinkedList(arr: [Int]) -> ListNode? { + let dum = ListNode(x: 0) + var head: ListNode? = dum + for val in arr { + head?.next = ListNode(x: val) + head = head?.next + } + return dum.next + } } diff --git a/docs/chapter_searching/binary_search.md b/docs/chapter_searching/binary_search.md index 9c0485614..6452d4cf1 100644 --- a/docs/chapter_searching/binary_search.md +++ b/docs/chapter_searching/binary_search.md @@ -213,7 +213,25 @@ $$ === "Swift" ```swift title="binary_search.swift" - + /* 二分查找(双闭区间) */ + func binarySearch(nums: [Int], target: Int) -> Int { + // 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素 + var i = 0 + var j = nums.count - 1 + // 循环,当搜索区间为空时跳出(当 i > j 时为空) + while i <= j { + let m = (i + j) / 2 // 计算中点索引 m + if nums[m] < target { // 此情况说明 target 在区间 [m+1, j] 中 + i = m + 1 + } else if nums[m] > target { // 此情况说明 target 在区间 [i, m-1] 中 + j = m - 1 + } else { // 找到目标元素,返回其索引 + return m + } + } + // 未找到目标元素,返回 -1 + return -1 + } ``` ### “左闭右开”实现 @@ -383,7 +401,25 @@ $$ === "Swift" ```swift title="binary_search.swift" - + /* 二分查找(左闭右开) */ + func binarySearch1(nums: [Int], target: Int) -> Int { + // 初始化左闭右开 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1 + var i = 0 + var j = nums.count + // 循环,当搜索区间为空时跳出(当 i = j 时为空) + while i < j { + let m = (i + j) / 2 // 计算中点索引 m + if nums[m] < target { // 此情况说明 target 在区间 [m+1, j) 中 + i = m + 1 + } else if nums[m] > target { // 此情况说明 target 在区间 [i, m) 中 + j = m + } else { // 找到目标元素,返回其索引 + return m + } + } + // 未找到目标元素,返回 -1 + return -1 + } ``` ### 两种表示对比 @@ -475,7 +511,10 @@ $$ === "Swift" ```swift title="" - + // (i + j) 有可能超出 int 的取值范围 + let m = (i + j) / 2 + // 更换为此写法则不会越界 + let m = i + (j - 1) / 2 ``` ## 复杂度分析 diff --git a/docs/chapter_searching/hashing_search.md b/docs/chapter_searching/hashing_search.md index 9f3d74c0c..e58ec4f14 100644 --- a/docs/chapter_searching/hashing_search.md +++ b/docs/chapter_searching/hashing_search.md @@ -108,7 +108,12 @@ comments: true === "Swift" ```swift title="hashing_search.swift" - + /* 哈希查找(数组) */ + func hashingSearch(map: [Int: Int], target: Int) -> Int { + // 哈希表的 key: 目标元素,value: 索引 + // 若哈希表中无此 key ,返回 -1 + return map[target, default: -1] + } ``` 再比如,如果我们想要给定一个目标结点值 `target` ,获取对应的链表结点对象,那么也可以使用哈希查找实现。 @@ -208,7 +213,12 @@ comments: true === "Swift" ```swift title="hashing_search.swift" - + /* 哈希查找(链表) */ + func hashingSearch1(map: [Int: ListNode], target: Int) -> ListNode? { + // 哈希表的 key: 目标结点值,value: 结点对象 + // 若哈希表中无此 key ,返回 null + return map[target] + } ``` ## 复杂度分析 diff --git a/docs/chapter_searching/linear_search.md b/docs/chapter_searching/linear_search.md index a42ccc365..bbbb9e6f6 100644 --- a/docs/chapter_searching/linear_search.md +++ b/docs/chapter_searching/linear_search.md @@ -136,7 +136,18 @@ comments: true === "Swift" ```swift title="linear_search.swift" - + /* 线性查找(数组) */ + func linearSearch(nums: [Int], target: Int) -> Int { + // 遍历数组 + for i in nums.indices { + // 找到目标元素,返回其索引 + if nums[i] == target { + return i + } + } + // 未找到目标元素,返回 -1 + return -1 + } ``` 再比如,我们想要在给定一个目标结点值 `target` ,返回此结点对象,也可以在链表中进行线性查找。 @@ -270,7 +281,20 @@ comments: true === "Swift" ```swift title="linear_search.swift" - + /* 线性查找(链表) */ + func linearSearch(head: ListNode?, target: Int) -> ListNode? { + var head = head + // 遍历链表 + while head != nil { + // 找到目标结点,返回之 + if head?.val == target { + return head + } + head = head?.next + } + // 未找到目标结点,返回 null + return nil + } ``` ## 复杂度分析