From 99f149493946e6c1bdef9c533273db527bc901e6 Mon Sep 17 00:00:00 2001 From: nuomi1 Date: Wed, 11 Jan 2023 23:48:10 +0800 Subject: [PATCH 1/2] feat: add Swift codes for queue article --- codes/swift/Package.swift | 6 + .../chapter_stack_and_queue/array_queue.swift | 116 ++++++++++++++++ .../linkedlist_queue.swift | 105 ++++++++++++++ .../swift/chapter_stack_and_queue/queue.swift | 39 ++++++ docs/chapter_stack_and_queue/queue.md | 129 ++++++++++++++++++ 5 files changed, 395 insertions(+) create mode 100644 codes/swift/chapter_stack_and_queue/array_queue.swift create mode 100644 codes/swift/chapter_stack_and_queue/linkedlist_queue.swift create mode 100644 codes/swift/chapter_stack_and_queue/queue.swift diff --git a/codes/swift/Package.swift b/codes/swift/Package.swift index 6d6eaa8a5..89c03d9f6 100644 --- a/codes/swift/Package.swift +++ b/codes/swift/Package.swift @@ -16,6 +16,9 @@ let package = Package( .executable(name: "stack", targets: ["stack"]), .executable(name: "linkedlist_stack", targets: ["linkedlist_stack"]), .executable(name: "array_stack", targets: ["array_stack"]), + .executable(name: "queue", targets: ["queue"]), + .executable(name: "linkedlist_queue", targets: ["linkedlist_queue"]), + .executable(name: "array_queue", targets: ["array_queue"]), ], targets: [ .target(name: "utils", path: "utils"), @@ -30,5 +33,8 @@ let package = Package( .executableTarget(name: "stack", path: "chapter_stack_and_queue", sources: ["stack.swift"]), .executableTarget(name: "linkedlist_stack", dependencies: ["utils"], path: "chapter_stack_and_queue", sources: ["linkedlist_stack.swift"]), .executableTarget(name: "array_stack", path: "chapter_stack_and_queue", sources: ["array_stack.swift"]), + .executableTarget(name: "queue", path: "chapter_stack_and_queue", sources: ["queue.swift"]), + .executableTarget(name: "linkedlist_queue", dependencies: ["utils"], path: "chapter_stack_and_queue", sources: ["linkedlist_queue.swift"]), + .executableTarget(name: "array_queue", path: "chapter_stack_and_queue", sources: ["array_queue.swift"]), ] ) diff --git a/codes/swift/chapter_stack_and_queue/array_queue.swift b/codes/swift/chapter_stack_and_queue/array_queue.swift new file mode 100644 index 000000000..d76dbc9c5 --- /dev/null +++ b/codes/swift/chapter_stack_and_queue/array_queue.swift @@ -0,0 +1,116 @@ +/** + * File: array_queue.swift + * Created Time: 2023-01-11 + * Author: nuomi1 (nuomi1@qq.com) + */ + +/* 基于环形数组实现的队列 */ +class ArrayQueue { + private var nums: [Int] // 用于存储队列元素的数组 + private var front = 0 // 头指针,指向队首 + private var rear = 0 // 尾指针,指向队尾 + 1 + + init(capacity: Int) { + // 初始化数组 + nums = Array(repeating: 0, count: capacity) + } + + /* 获取队列的容量 */ + func capacity() -> Int { + nums.count + } + + /* 获取队列的长度 */ + func size() -> Int { + let capacity = capacity() + // 由于将数组看作为环形,可能 rear < front ,因此需要取余数 + return (capacity + rear - front) % capacity + } + + /* 判断队列是否为空 */ + func isEmpty() -> Bool { + rear - front == 0 + } + + /* 入队 */ + func offer(num: Int) { + if size() == capacity() { + print("队列已满") + return + } + // 尾结点后添加 num + nums[rear] = num + // 尾指针向后移动一位,越过尾部后返回到数组头部 + rear = (rear + 1) % capacity() + } + + /* 出队 */ + @discardableResult + func poll() -> Int { + let num = peek() + // 队头指针向后移动一位,若越过尾部则返回到数组头部 + front = (front + 1) % capacity() + return num + } + + /* 访问队首元素 */ + func peek() -> Int { + if isEmpty() { + fatalError("队列为空") + } + return nums[front] + } + + /* 返回数组 */ + func toArray() -> [Int] { + let size = size() + let capacity = capacity() + // 仅转换有效长度范围内的列表元素 + var res = Array(repeating: 0, count: size) + for (i, j) in sequence(first: (0, front), next: { $0 < size - 1 ? ($0 + 1, $1 + 1) : nil }) { + res[i] = nums[j % capacity] + } + return res + } +} + +@main +enum _ArrayQueue { + /* Driver Code */ + static func main() { + /* 初始化队列 */ + let capacity = 10 + let queue = ArrayQueue(capacity: capacity) + + /* 元素入队 */ + queue.offer(num: 1) + queue.offer(num: 3) + queue.offer(num: 2) + queue.offer(num: 5) + queue.offer(num: 4) + print("队列 queue = \(queue.toArray())") + + /* 访问队首元素 */ + let peek = queue.peek() + print("队首元素 peek = \(peek)") + + /* 元素出队 */ + let poll = queue.poll() + print("出队元素 poll = \(poll),出队后 queue = \(queue.toArray())") + + /* 获取队列的长度 */ + let size = queue.size() + print("队列长度 size = \(size)") + + /* 判断队列是否为空 */ + let isEmpty = queue.isEmpty() + print("队列是否为空 = \(isEmpty)") + + /* 测试环形数组 */ + for i in 0 ..< 10 { + queue.offer(num: i) + queue.poll() + print("第 \(i) 轮入队 + 出队后 queue = \(queue.toArray())") + } + } +} diff --git a/codes/swift/chapter_stack_and_queue/linkedlist_queue.swift b/codes/swift/chapter_stack_and_queue/linkedlist_queue.swift new file mode 100644 index 000000000..1d671742b --- /dev/null +++ b/codes/swift/chapter_stack_and_queue/linkedlist_queue.swift @@ -0,0 +1,105 @@ +/** + * File: linkedlist_queue.swift + * Created Time: 2023-01-11 + * Author: nuomi1 (nuomi1@qq.com) + */ + +import utils + +/* 基于链表实现的队列 */ +class LinkedListQueue { + private var front: ListNode? // 头结点 + private var rear: ListNode? // 尾结点 + private var _size = 0 + + init() {} + + /* 获取队列的长度 */ + func size() -> Int { + _size + } + + /* 判断队列是否为空 */ + func isEmpty() -> Bool { + size() == 0 + } + + /* 入队 */ + func offer(num: Int) { + // 尾结点后添加 num + let node = ListNode(x: num) + // 如果队列为空,则令头、尾结点都指向该结点 + if front == nil { + front = node + rear = node + } + // 如果队列不为空,则将该结点添加到尾结点后 + else { + rear?.next = node + rear = node + } + _size += 1 + } + + /* 出队 */ + @discardableResult + func poll() -> Int { + let num = peek() + // 删除头结点 + front = front?.next + _size -= 1 + return num + } + + /* 访问队首元素 */ + func peek() -> Int { + if isEmpty() { + fatalError("队列为空") + } + return front!.val + } + + /* 将链表转化为 Array 并返回 */ + func toArray() -> [Int] { + var node = front + var res = Array(repeating: 0, count: size()) + for i in res.indices { + res[i] = node!.val + node = node?.next + } + return res + } +} + +@main +enum _LinkedListQueue { + /* Driver Code */ + static func main() { + /* 初始化队列 */ + let queue = LinkedListQueue() + + /* 元素入队 */ + queue.offer(num: 1) + queue.offer(num: 3) + queue.offer(num: 2) + queue.offer(num: 5) + queue.offer(num: 4) + print("队列 queue = \(queue.toArray())") + + /* 访问队首元素 */ + let peek = queue.peek() + print("队首元素 peek = \(peek)") + + /* 元素出队 */ + let poll = queue.poll() + print("出队元素 poll = \(poll),出队后 queue = \(queue.toArray())") + + /* 获取队列的长度 */ + let size = queue.size() + print("队列长度 size = \(size)") + + /* 判断队列是否为空 */ + let isEmpty = queue.isEmpty() + print("队列是否为空 = \(isEmpty)") + } +} diff --git a/codes/swift/chapter_stack_and_queue/queue.swift b/codes/swift/chapter_stack_and_queue/queue.swift new file mode 100644 index 000000000..f13af36f5 --- /dev/null +++ b/codes/swift/chapter_stack_and_queue/queue.swift @@ -0,0 +1,39 @@ +/** + * File: queue.swift + * Created Time: 2023-01-11 + * Author: nuomi1 (nuomi1@qq.com) + */ + +@main +enum Queue { + /* Driver Code */ + static func main() { + /* 初始化队列 */ + // Swift 没有内置的队列类,可以把 Array 当作队列来使用 + var queue: [Int] = [] + + /* 元素入队 */ + queue.append(1) + queue.append(3) + queue.append(2) + queue.append(5) + queue.append(4) + print("队列 queue = \(queue)") + + /* 访问队首元素 */ + let peek = queue.first! + print("队首元素 peek = \(peek)") + + /* 元素出队 */ + let pool = queue.removeFirst() + print("出队元素 poll = \(pool),出队后 queue = \(queue)") + + /* 获取队列的长度 */ + let size = queue.count + print("队列长度 size = \(size)") + + /* 判断队列是否为空 */ + let isEmpty = queue.isEmpty + print("队列是否为空 = \(isEmpty)") + } +} diff --git a/docs/chapter_stack_and_queue/queue.md b/docs/chapter_stack_and_queue/queue.md index 0c589fa69..08cf76d78 100644 --- a/docs/chapter_stack_and_queue/queue.md +++ b/docs/chapter_stack_and_queue/queue.md @@ -231,7 +231,28 @@ comments: true === "Swift" ```swift title="queue.swift" + /* 初始化队列 */ + // Swift 没有内置的队列类,可以把 Array 当作队列来使用 + var queue: [Int] = [] + /* 元素入队 */ + queue.append(1) + queue.append(3) + queue.append(2) + queue.append(5) + queue.append(4) + + /* 访问队首元素 */ + let peek = queue.first! + + /* 元素出队 */ + let pool = queue.removeFirst() + + /* 获取队列的长度 */ + let size = queue.count + + /* 判断队列是否为空 */ + let isEmpty = queue.isEmpty ``` ## 队列实现 @@ -627,7 +648,59 @@ comments: true === "Swift" ```swift title="linkedlist_queue.swift" + /* 基于链表实现的队列 */ + class LinkedListQueue { + private var front: ListNode? // 头结点 + private var rear: ListNode? // 尾结点 + private var _size = 0 + init() {} + + /* 获取队列的长度 */ + func size() -> Int { + _size + } + + /* 判断队列是否为空 */ + func isEmpty() -> Bool { + size() == 0 + } + + /* 入队 */ + func offer(num: Int) { + // 尾结点后添加 num + let node = ListNode(x: num) + // 如果队列为空,则令头、尾结点都指向该结点 + if front == nil { + front = node + rear = node + } + // 如果队列不为空,则将该结点添加到尾结点后 + else { + rear?.next = node + rear = node + } + _size += 1 + } + + /* 出队 */ + @discardableResult + func poll() -> Int { + let num = peek() + // 删除头结点 + front = front?.next + _size -= 1 + return num + } + + /* 访问队首元素 */ + func peek() -> Int { + if isEmpty() { + fatalError("队列为空") + } + return front!.val + } + } ``` ### 基于数组的实现 @@ -1042,7 +1115,63 @@ comments: true === "Swift" ```swift title="array_queue.swift" + /* 基于环形数组实现的队列 */ + class ArrayQueue { + private var nums: [Int] // 用于存储队列元素的数组 + private var front = 0 // 头指针,指向队首 + private var rear = 0 // 尾指针,指向队尾 + 1 + init(capacity: Int) { + // 初始化数组 + nums = Array(repeating: 0, count: capacity) + } + + /* 获取队列的容量 */ + func capacity() -> Int { + nums.count + } + + /* 获取队列的长度 */ + func size() -> Int { + let capacity = capacity() + // 由于将数组看作为环形,可能 rear < front ,因此需要取余数 + return (capacity + rear - front) % capacity + } + + /* 判断队列是否为空 */ + func isEmpty() -> Bool { + rear - front == 0 + } + + /* 入队 */ + func offer(num: Int) { + if size() == capacity() { + print("队列已满") + return + } + // 尾结点后添加 num + nums[rear] = num + // 尾指针向后移动一位,越过尾部后返回到数组头部 + rear = (rear + 1) % capacity() + } + + /* 出队 */ + @discardableResult + func poll() -> Int { + let num = peek() + // 队头指针向后移动一位,若越过尾部则返回到数组头部 + front = (front + 1) % capacity() + return num + } + + /* 访问队首元素 */ + func peek() -> Int { + if isEmpty() { + fatalError("队列为空") + } + return nums[front] + } + } ``` ## 队列典型应用 From ac7d26c131c834d10fe951cd3615264a97a5f4fc Mon Sep 17 00:00:00 2001 From: nuomi1 Date: Wed, 11 Jan 2023 23:54:04 +0800 Subject: [PATCH 2/2] refactor: use internal method and remove toArray() method --- .../chapter_stack_and_queue/array_stack.swift | 5 ++-- .../linkedlist_stack.swift | 5 ++-- docs/chapter_stack_and_queue/stack.md | 26 +++++-------------- 3 files changed, 12 insertions(+), 24 deletions(-) diff --git a/codes/swift/chapter_stack_and_queue/array_stack.swift b/codes/swift/chapter_stack_and_queue/array_stack.swift index faeeaa173..144ebec95 100644 --- a/codes/swift/chapter_stack_and_queue/array_stack.swift +++ b/codes/swift/chapter_stack_and_queue/array_stack.swift @@ -29,8 +29,9 @@ class ArrayStack { } /* 出栈 */ + @discardableResult func pop() -> Int { - if stack.isEmpty { + if isEmpty() { fatalError("栈为空") } return stack.removeLast() @@ -38,7 +39,7 @@ class ArrayStack { /* 访问栈顶元素 */ func peek() -> Int { - if stack.isEmpty { + if isEmpty() { fatalError("栈为空") } return stack.last! diff --git a/codes/swift/chapter_stack_and_queue/linkedlist_stack.swift b/codes/swift/chapter_stack_and_queue/linkedlist_stack.swift index 9d3c98b01..97f7dabcc 100644 --- a/codes/swift/chapter_stack_and_queue/linkedlist_stack.swift +++ b/codes/swift/chapter_stack_and_queue/linkedlist_stack.swift @@ -20,7 +20,7 @@ class LinkedListStack { /* 判断栈是否为空 */ func isEmpty() -> Bool { - _size == 0 + size() == 0 } /* 入栈 */ @@ -32,6 +32,7 @@ class LinkedListStack { } /* 出栈 */ + @discardableResult func pop() -> Int { let num = peek() _peek = _peek?.next @@ -41,7 +42,7 @@ class LinkedListStack { /* 访问栈顶元素 */ func peek() -> Int { - if _size == 0 { + if isEmpty() { fatalError("栈为空") } return _peek!.val diff --git a/docs/chapter_stack_and_queue/stack.md b/docs/chapter_stack_and_queue/stack.md index 04825695c..7ff3f15bf 100644 --- a/docs/chapter_stack_and_queue/stack.md +++ b/docs/chapter_stack_and_queue/stack.md @@ -641,7 +641,7 @@ comments: true /* 判断栈是否为空 */ func isEmpty() -> Bool { - _size == 0 + size() == 0 } /* 入栈 */ @@ -653,6 +653,7 @@ comments: true } /* 出栈 */ + @discardableResult func pop() -> Int { let num = peek() _peek = _peek?.next @@ -662,22 +663,11 @@ comments: true /* 访问栈顶元素 */ func peek() -> Int { - if _size == 0 { + if isEmpty() { fatalError("栈为空") } return _peek!.val } - - /* 将 List 转化为 Array 并返回 */ - func toArray() -> [Int] { - var node = _peek - var res = Array(repeating: 0, count: _size) - for i in sequence(first: res.count - 1, next: { $0 >= 0 + 1 ? $0 - 1 : nil }) { - res[i] = node!.val - node = node?.next - } - return res - } } ``` @@ -994,8 +984,9 @@ comments: true } /* 出栈 */ + @discardableResult func pop() -> Int { - if stack.isEmpty { + if isEmpty() { fatalError("栈为空") } return stack.removeLast() @@ -1003,16 +994,11 @@ comments: true /* 访问栈顶元素 */ func peek() -> Int { - if stack.isEmpty { + if isEmpty() { fatalError("栈为空") } return stack.last! } - - /* 将 List 转化为 Array 并返回 */ - func toArray() -> [Int] { - stack - } } ```