diff --git a/codes/swift/Package.swift b/codes/swift/Package.swift index a6eeaf2ee..ce631660b 100644 --- a/codes/swift/Package.swift +++ b/codes/swift/Package.swift @@ -23,6 +23,8 @@ let package = Package( .executable(name: "linkedlist_queue", targets: ["linkedlist_queue"]), .executable(name: "array_queue", targets: ["array_queue"]), .executable(name: "deque", targets: ["deque"]), + .executable(name: "linkedlist_deque", targets: ["linkedlist_deque"]), + .executable(name: "array_deque", targets: ["array_deque"]), // chapter_hashing .executable(name: "hash_map", targets: ["hash_map"]), .executable(name: "array_hash_map", targets: ["array_hash_map"]), @@ -72,6 +74,8 @@ let package = Package( .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"]), .executableTarget(name: "deque", path: "chapter_stack_and_queue", sources: ["deque.swift"]), + .executableTarget(name: "linkedlist_deque", path: "chapter_stack_and_queue", sources: ["linkedlist_deque.swift"]), + .executableTarget(name: "array_deque", path: "chapter_stack_and_queue", sources: ["array_deque.swift"]), // chapter_hashing .executableTarget(name: "hash_map", dependencies: ["utils"], path: "chapter_hashing", sources: ["hash_map.swift"]), .executableTarget(name: "array_hash_map", path: "chapter_hashing", sources: ["array_hash_map.swift"]), diff --git a/codes/swift/chapter_stack_and_queue/array_deque.swift b/codes/swift/chapter_stack_and_queue/array_deque.swift new file mode 100644 index 000000000..8c291bf43 --- /dev/null +++ b/codes/swift/chapter_stack_and_queue/array_deque.swift @@ -0,0 +1,152 @@ +/** + * File: array_deque.swift + * Created Time: 2023-02-22 + * Author: nuomi1 (nuomi1@qq.com) + */ + +/* 基于环形数组实现的双向队列 */ +class ArrayDeque { + private var nums: [Int] // 用于存储双向队列元素的数组 + private var front: Int // 队首指针,指向队首元素 + private var queSize: Int // 双向队列长度 + + /* 构造方法 */ + init(capacity: Int) { + nums = Array(repeating: 0, count: capacity) + front = 0 + queSize = 0 + } + + /* 获取双向队列的容量 */ + func capacity() -> Int { + nums.count + } + + /* 获取双向队列的长度 */ + func size() -> Int { + queSize + } + + /* 判断双向队列是否为空 */ + func isEmpty() -> Bool { + size() == 0 + } + + /* 计算环形数组索引 */ + private func index(i: Int) -> Int { + // 通过取余操作实现数组首尾相连 + // 当 i 越过数组尾部后,回到头部 + // 当 i 越过数组头部后,回到尾部 + (i + capacity()) % capacity() + } + + /* 队首入队 */ + func pushFirst(num: Int) { + if size() == capacity() { + print("双向队列已满") + return + } + // 队首指针向左移动一位 + // 通过取余操作,实现 front 越过数组头部后回到尾部 + front = index(i: front - 1) + // 将 num 添加至队首 + nums[front] = num + queSize += 1 + } + + /* 队尾入队 */ + func pushLast(num: Int) { + if size() == capacity() { + print("双向队列已满") + return + } + // 计算尾指针,指向队尾索引 + 1 + let rear = index(i: front + size()) + // 将 num 添加至队尾 + nums[rear] = num + queSize += 1 + } + + /* 队首出队 */ + func pollFirst() -> Int { + let num = peekFirst() + // 队首指针向后移动一位 + front = index(i: front + 1) + queSize -= 1 + return num + } + + /* 队尾出队 */ + func pollLast() -> Int { + let num = peekLast() + queSize -= 1 + return num + } + + /* 访问队首元素 */ + func peekFirst() -> Int { + if isEmpty() { + fatalError("双向队列为空") + } + return nums[front] + } + + /* 访问队尾元素 */ + func peekLast() -> Int { + if isEmpty() { + fatalError("双向队列为空") + } + // 计算尾元素索引 + let last = index(i: front + size() - 1) + return nums[last] + } + + /* 返回数组用于打印 */ + func toArray() -> [Int] { + // 仅转换有效长度范围内的列表元素 + var res = Array(repeating: 0, count: size()) + for (i, j) in sequence(first: (0, front), next: { $0 < self.size() - 1 ? ($0 + 1, $1 + 1) : nil }) { + res[i] = nums[index(i: j)] + } + return res + } +} + +@main +enum _ArrayDeque { + /* Driver Code */ + static func main() { + /* 初始化双向队列 */ + let deque = ArrayDeque(capacity: 10) + deque.pushLast(num: 3) + deque.pushLast(num: 2) + deque.pushLast(num: 5) + print("双向队列 deque = \(deque.toArray())") + + /* 访问元素 */ + let peekFirst = deque.peekFirst() + print("队首元素 peekFirst = \(peekFirst)") + let peekLast = deque.peekLast() + print("队尾元素 peekLast = \(peekLast)") + + /* 元素入队 */ + deque.pushLast(num: 4) + print("元素 4 队尾入队后 deque = \(deque.toArray())") + deque.pushFirst(num: 1) + print("元素 1 队首入队后 deque = \(deque.toArray())") + + /* 元素出队 */ + let pollLast = deque.pollLast() + print("队尾出队元素 = \(pollLast),队尾出队后 deque = \(deque.toArray())") + let pollFirst = deque.pollFirst() + print("队首出队元素 = \(pollFirst),队首出队后 deque = \(deque.toArray())") + + /* 获取双向队列的长度 */ + let size = deque.size() + print("双向队列长度 size = \(size)") + + /* 判断双向队列是否为空 */ + let isEmpty = deque.isEmpty() + print("双向队列是否为空 = \(isEmpty)") + } +} diff --git a/codes/swift/chapter_stack_and_queue/linkedlist_deque.swift b/codes/swift/chapter_stack_and_queue/linkedlist_deque.swift new file mode 100644 index 000000000..b1ae7806f --- /dev/null +++ b/codes/swift/chapter_stack_and_queue/linkedlist_deque.swift @@ -0,0 +1,174 @@ +/** + * File: linkedlist_deque.swift + * Created Time: 2023-02-22 + * Author: nuomi1 (nuomi1@qq.com) + */ + +/* 双向链表结点 */ +class ListNode { + var val: Int // 结点值 + var next: ListNode? // 后继结点引用(指针) + var prev: ListNode? // 前驱结点引用(指针) + + init(val: Int) { + self.val = val + } +} + +/* 基于双向链表实现的双向队列 */ +class LinkedListDeque { + private var front: ListNode? // 头结点 front + private var rear: ListNode? // 尾结点 rear + private var queSize: Int // 双向队列的长度 + + init() { + queSize = 0 + } + + /* 获取双向队列的长度 */ + func size() -> Int { + queSize + } + + /* 判断双向队列是否为空 */ + func isEmpty() -> Bool { + size() == 0 + } + + /* 入队操作 */ + private func push(num: Int, isFront: Bool) { + let node = ListNode(val: num) + // 若链表为空,则令 front, rear 都指向 node + if isEmpty() { + front = node + rear = node + } + // 队首入队操作 + else if isFront { + // 将 node 添加至链表头部 + front?.prev = node + node.next = front + front = node // 更新头结点 + } + // 队尾入队操作 + else { + // 将 node 添加至链表尾部 + rear?.next = node + node.prev = rear + rear = node // 更新尾结点 + } + queSize += 1 // 更新队列长度 + } + + /* 队首入队 */ + func pushFirst(num: Int) { + push(num: num, isFront: true) + } + + /* 队尾入队 */ + func pushLast(num: Int) { + push(num: num, isFront: false) + } + + /* 出队操作 */ + private func poll(isFront: Bool) -> Int { + if isEmpty() { + fatalError("双向队列为空") + } + let val: Int + // 队首出队操作 + if isFront { + val = front!.val // 暂存头结点值 + // 删除头结点 + let fNext = front?.next + if fNext != nil { + fNext?.prev = nil + front?.next = nil + } + front = fNext // 更新头结点 + } + // 队尾出队操作 + else { + val = rear!.val // 暂存尾结点值 + // 删除尾结点 + let rPrev = rear?.prev + if rPrev != nil { + rPrev?.next = nil + rear?.prev = nil + } + rear = rPrev // 更新尾结点 + } + queSize -= 1 // 更新队列长度 + return val + } + + /* 队首出队 */ + func pollFirst() -> Int { + poll(isFront: true) + } + + /* 队尾出队 */ + func pollLast() -> Int { + poll(isFront: false) + } + + /* 访问队首元素 */ + func peekFirst() -> Int? { + isEmpty() ? nil : front?.val + } + + /* 访问队尾元素 */ + func peekLast() -> Int? { + isEmpty() ? nil : rear?.val + } + + /* 返回数组用于打印 */ + 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 _LinkedListDeque { + /* Driver Code */ + static func main() { + /* 初始化双向队列 */ + let deque = LinkedListDeque() + deque.pushLast(num: 3) + deque.pushLast(num: 2) + deque.pushLast(num: 5) + print("双向队列 deque = \(deque.toArray())") + + /* 访问元素 */ + let peekFirst = deque.peekFirst() + print("队首元素 peekFirst = \(peekFirst!)") + let peekLast = deque.peekLast() + print("队尾元素 peekLast = \(peekLast!)") + + /* 元素入队 */ + deque.pushLast(num: 4) + print("元素 4 队尾入队后 deque = \(deque.toArray())") + deque.pushFirst(num: 1) + print("元素 1 队首入队后 deque = \(deque.toArray())") + + /* 元素出队 */ + let pollLast = deque.pollLast() + print("队尾出队元素 = \(pollLast),队尾出队后 deque = \(deque.toArray())") + let pollFirst = deque.pollFirst() + print("队首出队元素 = \(pollFirst),队首出队后 deque = \(deque.toArray())") + + /* 获取双向队列的长度 */ + let size = deque.size() + print("双向队列长度 size = \(size)") + + /* 判断双向队列是否为空 */ + let isEmpty = deque.isEmpty() + print("双向队列是否为空 = \(isEmpty)") + } +} diff --git a/docs/chapter_stack_and_queue/deque.md b/docs/chapter_stack_and_queue/deque.md index 000f1d17e..e7d6462c5 100644 --- a/docs/chapter_stack_and_queue/deque.md +++ b/docs/chapter_stack_and_queue/deque.md @@ -381,7 +381,9 @@ comments: true === "Swift" ```swift title="linkedlist_deque.swift" + [class]{ListNode}-[func]{} + [class]{LinkedListDeque}-[func]{} ``` === "Zig" @@ -462,7 +464,7 @@ comments: true === "Swift" ```swift title="array_deque.swift" - + [class]{ArrayDeque}-[func]{} ``` === "Zig"