From fc167fd11f284e64b800b583e5bec6382e762548 Mon Sep 17 00:00:00 2001 From: Jiandan Date: Thu, 11 Oct 2018 22:56:35 +0800 Subject: [PATCH] [swift] [09_queue] [add] --- swift/09_queue/ArrayQueue.swift | 112 ++++++++++++++++++++ swift/09_queue/CircularQueue.swift | 63 +++++++++++ swift/09_queue/Queue.swift | 21 ++++ swift/09_queue/QueueBasedOnLinkedList.swift | 61 +++++++++++ 4 files changed, 257 insertions(+) create mode 100644 swift/09_queue/ArrayQueue.swift create mode 100644 swift/09_queue/CircularQueue.swift create mode 100644 swift/09_queue/Queue.swift create mode 100644 swift/09_queue/QueueBasedOnLinkedList.swift diff --git a/swift/09_queue/ArrayQueue.swift b/swift/09_queue/ArrayQueue.swift new file mode 100644 index 0000000..1dea014 --- /dev/null +++ b/swift/09_queue/ArrayQueue.swift @@ -0,0 +1,112 @@ +// +// Created by Jiandan on 2018/10/11. +// Copyright (c) 2018 Jiandan. All rights reserved. +// + +import Foundation + +/// 用数组实现的队列 +struct ArrayQueue: Queue { + typealias Element = T + + /// 数组 + private var items: [Element] + /// 数组最大长度 + private var capacity = 0 + /// 队头下标 + private var head = 0 + /// 队尾下标 + private var tail = 0 + + /// 构造方法 + /// - parameter defaultElement: 默认元素 + /// - parameter capacity: 数组长度 + init(defaultElement: Element, capacity: Int) { + self.capacity = capacity + items = [Element](repeating: defaultElement, count: capacity) + } + + // MARK: Protocol: Queue + + var isEmpty: Bool { return head == tail } + + var size: Int { return tail - head } + + var peek: Element? { return isEmpty ? nil : items[head] } + + // 没有数据搬移的实现,即实现了一个有界序列 +// mutating func enqueue(newElement: Element) -> Bool { +// // 整个队列都占满了 +// if tail == capacity { +// return false +// } +// +// items[tail] = newElement +// tail += 1 +// return true +// } + // 有数据搬移的实现,即实现了一个无界序列 + mutating func enqueue(newElement: Element) -> Bool { + // 如果 tail == capacity 表示队列末尾没有空间了 + if tail == capacity { + // 整个队列都占满了 + if head == 0 { return false } + // 数据搬移 + for i in head ..< tail { + items[i - head] = items[i] + } + // 搬移完之后重新更新 head 和 tail + tail -= head + head = 0 + } + + items[tail] = newElement + tail += 1 + return true + } + + mutating func dequeue() -> Element? { + if isEmpty { + return nil + } + + let item = items[head] + head += 1 + return item + } +} + +/// 使用2个数组实现无界队列,用到 Swift 中 Array 较多的方法 +/// 来源:《iOS 面试之道》(故胤道长,唐巧) +struct ArrayQueue2: Queue { + typealias Element = T + + /// 输入数组,主要负责入队 + var inArray = [Element]() + /// 输出数组,主要负责出队 + var outArray = [Element]() + + var isEmpty: Bool { return inArray.isEmpty && outArray.isEmpty } + + var size: Int { return inArray.count + outArray.count } + + // 当 outArray 为空时,返回 inArray 首个元素,否则返回 outArray 末尾元素 + var peek: Element? { return outArray.isEmpty ? inArray.first : outArray.last } + + mutating func enqueue(newElement: Element) -> Bool { + // inArray 添加元素 + inArray.append(newElement) + return true + } + + mutating func dequeue() -> Element? { + if outArray.isEmpty { + // 将 inArray 倒序存入 outArray 中 + outArray = inArray.reversed() + // 清空 inArray + inArray.removeAll() + } + // 弹出 outArray 最后一个元素 + return outArray.popLast() + } +} diff --git a/swift/09_queue/CircularQueue.swift b/swift/09_queue/CircularQueue.swift new file mode 100644 index 0000000..6a58f98 --- /dev/null +++ b/swift/09_queue/CircularQueue.swift @@ -0,0 +1,63 @@ +// +// Created by Jiandan on 2018/10/11. +// Copyright (c) 2018 Jiandan. All rights reserved. +// + +import Foundation + +/// 循环队列 +struct CircularQueue: Queue { + typealias Element = T + + /// 数组 + private var items: [Element] + /// 数组最大长度 + private var capacity = 0 + /// 队头下标 + private var head = 0 + /// 队尾下标 + private var tail = 0 + + /// 构造方法 + /// - parameter defaultElement: 默认元素 + /// - parameter capacity: 数组长度 + init(defaultElement: Element, capacity: Int) { + self.capacity = capacity + items = [Element](repeating: defaultElement, count: capacity) + } + + // MARK: Protocol: Queue + + var isEmpty: Bool { return head == tail } + + var size: Int { + if tail >= head { + return tail - head + } else { + return (tail + 1) + (capacity - head) + } + } + + var peek: Element? { return isEmpty ? nil : items[head] } + + mutating func enqueue(newElement: Element) -> Bool { + // 整个队列都占满了 + if (tail + 1) % capacity == head { + return false + } + + items[tail] = newElement + tail = (tail + 1) % capacity + return true + } + + mutating func dequeue() -> Element? { + if isEmpty { + return nil + } + + let item = items[head] + head = (head + 1) % capacity + return item + } +} diff --git a/swift/09_queue/Queue.swift b/swift/09_queue/Queue.swift new file mode 100644 index 0000000..ab0bdd9 --- /dev/null +++ b/swift/09_queue/Queue.swift @@ -0,0 +1,21 @@ +// +// Created by Jiandan on 2018/10/11. +// Copyright (c) 2018 Jiandan. All rights reserved. +// + +import Foundation + +protocol Queue { + /// 持有的数据类型 + associatedtype Element + /// 是否为空 + var isEmpty: Bool { get } + /// 队列大小 + var size: Int { get } + /// 返回队列头部元素 + var peek: Element? { get } + /// 入队 + mutating func enqueue(newElement: Element) -> Bool + /// 出队 + mutating func dequeue() -> Element? +} diff --git a/swift/09_queue/QueueBasedOnLinkedList.swift b/swift/09_queue/QueueBasedOnLinkedList.swift new file mode 100644 index 0000000..be73795 --- /dev/null +++ b/swift/09_queue/QueueBasedOnLinkedList.swift @@ -0,0 +1,61 @@ +// +// Created by Jiandan on 2018/10/11. +// Copyright (c) 2018 Jiandan. All rights reserved. +// + +import Foundation + +class Node { + var value: T? + var next: Node? + + init(value: T) { + self.value = value + } +} + +struct QueueBasedOnLinkedList: Queue { + typealias Element = T + + /// 队首 + var head: Node? + /// 队尾 + var tail: Node? + + // MARK: Protocol: Queue + + var isEmpty: Bool { return head == nil } + + var size: Int { + var count = 0 + while head?.next != nil { + count += 1 + } + return count + } + + var peek: Element? { return head?.value } + + mutating func enqueue(newElement: Element) -> Bool { + if isEmpty { + // 空队列 + let node = Node(value: newElement) + head = node + tail = node + } else { + tail!.next = Node(value: newElement) + tail = tail!.next + } + return true + } + + mutating func dequeue() -> Element? { + if isEmpty { + return nil + } + + let node = head + head = head!.next + return node?.value + } +}