前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Swift算法俱乐部:Swift队列数据结构(Queue)

Swift算法俱乐部:Swift队列数据结构(Queue)

作者头像
Charlie_W
发布2018-10-19 14:55:50
8550
发布2018-10-19 14:55:50
举报
文章被收录于专栏:Charlie's RoadCharlie's Road

翻译自raywenderlich网站iOS教程Swift Algorithm Club系列

准备开始

队列(Queue)是一个列表,您只能在后面插入新项目并从前面删除项目。 这可确保入队的第一个元素也是首先出队的元素。 先到先出

在许多算法中,我们希望在某个时间点将项目添加到临时列表中,然后在以后再次将它们从列表中拉出。 添加和删除这些项目的顺序非常重要。

队列提供先进先出或先入先出的顺序。 首先插入的元素也是第一个出来的元素(和堆栈(Stack)非常类似,是LIFO或后进先出。)

这是一个栗子

理解队列的最简单方法是看看它是如何使用的。

想象一下你有一个队列。 以下是你如何入选一个数字:

代码语言:javascript
复制
queue.enqueue(10)

队列现在是10。 然后,继续将下一个号码添加到队列中:

代码语言:javascript
复制
queue.enqueue(3)

队列现在是10,3。 继续添加:

代码语言:javascript
复制
queue.enqueue(57)

队列现在是10,3,57。 我们可以将队列中的第一个元素从队列中拉出:

代码语言:javascript
复制
queue.dequeue()

将返回10,因为这是插入的第一个数字。 队列现在将是3,57。 每个项目都向上移动一个地方。

代码语言:javascript
复制
queue.dequeue()

这将返回3.下一个出列将返回57,依此类推。 如果队列为空,则出队将返回零。

实现队列

在本节中,将实现一个存储Int值的简单通用队列。

创建一个新的playground,添加如下代码:

代码语言:javascript
复制
public struct Queue {
    
}

playground还包含LinkedList的代码(可以通过转到查看 Project Navigators Show Project Navigator并打开Sources LinkedList来看到这一点。

入队(Enqueue)

队列需要入队方法。 我们使用项目中包含的LinkedList实现来实现队列。 在花括号之间添加以下内容:

代码语言:javascript
复制
// 1
fileprivate var list = LinkedList<Int>()

// 2
public mutating func enqueue(_ element: Int) {
    list.append(element)
}
  1. 添加了一个fileprivate LinkedList变量,用于将这些项目存储在队列中。
  2. 已经添加了一个方法来排列项目。 这个方法会改变底层的LinkedList,所以明确地指定了在方法前加上mutating关键字。

出列(Dequeue)

队列也需要一个出队方法。

代码语言:javascript
复制
// 1
public mutating func dequeque() -> Int? {
    // 2
    guard !list.isEmpty, let element = list.first else { return nil}
    
    list.remove(element)
    
    return element.value
}
  1. 添加一个返回队列中第一个项目的出队方法。 返回类型可以为空来处理队列为空。
  2. 使用guard语句处理队列为空。 如果这个队列是空的,那么guard将会进入else块。

查看(Peek)

队列还需要一个peek方法,它在队列的开始处返回该项目而不删除它。

代码语言:javascript
复制
public func peek() -> Int? {
  return list.first?.value
}

IsEmpty

队列可以是空的。 添加一个isEmpty属性,该属性将返回基于LinkedList的值:

代码语言:javascript
复制
public var isEmpty: Bool {
    return list.isEmpty
}

打印队列

让我们试试新队列。 在队列实现下面,将以下内容写入playground中:

代码语言:javascript
复制
var queue = Queue()
queue.enqueue(10)
queue.enqueue(3)
queue.enqueue(57)

定义队列后,尝试将队列打印到控制台:

代码语言:javascript
复制
print(queue)

输出如下:

代码语言:javascript
复制
Queue(list: [10, 3, 57])

这输出的样式不是很好。 要显示更可读的输出字符串,可以使队列采用CustomStringConvertable协议。 为此,请在Queue类的实现下方添加以下内容:

代码语言:javascript
复制
// 1
extension Queue: CustomStringConvertible {
    // 2
    public var description: String {
        // 3
        return list.description
    }
}
  1. 声明Queue类的扩展,让它遵循CustomStringConvertible协议。 该协议期望使用字符串类型实现带名称描述的计算属性。
  2. 声明了description属性。 这是一个计算属性,它是一个返回String的只读属性。
  3. 返回基于LinkedList的描述。

现在控制台的输出编程如下样式:

代码语言:javascript
复制
[10, 3, 57]

Swift通用队列实现

此时,我们已经实现了一个存储Int值的通用队列,并提供了在Queue类中查看,排队和出列项目的功能。

在本节中,我们使用泛型从队列中抽象出类型需求。

将Queue类的实现更新为以下内容:

代码语言:javascript
复制
// 1
public struct Queue<T> {
    // 2
    fileprivate var list = LinkedList<T>()
    
    // 3
    public mutating func enqueue(_ element: T) {
        list.append(element)
    }
    
    // 4
    public mutating func dequeque() -> T? {

        guard !list.isEmpty, let element = list.first else { return nil}
        
        list.remove(element)
        
        return element.value
    }
    // 5
    public func peek() -> T? {
        return list.first?.value
    }
    
    public var isEmpty: Bool {
        return list.isEmpty
    }
}

修正测试代码如下:

代码语言:javascript
复制
var queue = Queue<Int>()
queue.enqueue(10)
queue.enqueue(3)
queue.enqueue(57)
print(queue)

还可以尝试使用不同类型的Queue:

代码语言:javascript
复制
var queue2 = Queue<String>()
queue2.enqueue("mad")
queue2.enqueue("lad")
if let first = queue2.dequeque() {
    print(first)
}
print(queue2)

以上是本人在raywenderlich学习时为方便自己,用翻译工具翻译之后做的一个记录。

本系列其他文章:

Swift算法俱乐部:Swift栈(Stack)数据结构

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-06-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档