Swift数据结构引言

  了解不同数据结构的优劣,对我们今后的编程工作将十分有帮助(至于有什么帮助,可以自行百度,也可以翻书)。作为这个系列的第一篇博客,我们将重新复习一下Swift中几种内建的基本数据结构。

  通常情况下,从元素之间的关系上来讲,我们习惯上将数据结构分为两种基本类型:顺序存储数据结构和连式存储数据结构。顺序存储数据结构的特点是,逻辑关系上相邻的两个元素,它们在物理位置上也相邻,也就是说数据是存储在连续或者临近的内存中的,比如说数组、堆、矩阵和哈希表;而链式存储数据结构,其存储单元可以相邻,也可以不相邻。链式存储数据结构的元素,除了存储元素本身的数据信息之外,还会存储下一个(或者上一个)元素的信息。典型的链式存储结构有链表、树和图。你可以将这两种类型的数据结构综合起来使用,以便创建更加高效的数据结构。

一、顺序存储数据结构

  我们首先要学习的是顺序存储数据结构。这种数据结构是典型的线性数据结构,通常都是基于索引,并且数据元素的存取是按照一定的顺序执行的。

1、数组

  数组是最常见的数据结构,几乎在各种编程语言中都存在。线性数组,又称一维数组,是最简单的数组形式。在Swift中,数组是索引从0开始、按照顺序存储、可以随机访问的Collection(集合)类型。除了一维数组之外,数组也可以以多维数组的形式存在,比如说矩阵就是典型的多维数组。

(1)、数组的声明

  在Swift中,声明一个数组主要有三种方式,即:①、完整的数组声明方式,比如说使用泛型语法Array<Type>;②、使用快速简洁的方法,比如说[Type];③、最后一种方式是使用类型推断,也就是数组的字面量语法。通常情况下,我们使用得最多的是第二种方法。这三种声明数组方法的实例如下:

// 使用完整的泛型语法声明一个数组
let fullSyntaxForm: Array<String> = ["关羽", "张飞", "赵云", "马超", "黄忠"]

// 使用快速语法声明一个数组
let shorthandSyntaxForm: [String] = ["关羽", "张飞", "赵云", "马超", "黄忠"]

// 使用数组的字面量语法声明一个数组(不用特别指明数组的类型,变量的类型编译器会自动根据赋值推断)
let typeInferanceSyntaxForm = ["关羽", "张飞", "赵云", "马超", "黄忠"]  // 编译器自动推断其为字符串数组

  需要注意的是,使用类型推断功能的前提是,在声明数组的过程中明确的给它赋一个初始化值。另外,如果你在声明数组的过程中,不想给它赋值,而只想声明一个空的数组,可以使用以下语法:

// 利用完整的泛型语法声明一个空的数组
var fullSyntaxFor: Array<Int> = Array<Int>()

// 没有明确指明数组类型,但是在初始化的时候指明它是String类型
var shorthandSyntaxForm = [String]()  

// 在声明的时候明确指明了数组的类型是String类型,初始化的时候可以声明类型和括号
var shorthandSyntaxForm2: [String] = []  
(2)、访问数组中的元素

  访问数组中元素的方式有很多,最简单的是使用数组下标;如果你想取出数组中的某一段数据,还可以用范围来取出它里面的子序列;甚至,如果你想取出数组中所有的元素,也可以使用for…in或者forEach。有一点需要注意,在使用数组的下标时,千万不要越界,否则会引发编译错误:

var fiveTigerGeneral = ["关羽", "张飞", "赵云", "马超", "黄忠"]

// 通过下标来访问数组中的元素
let item = fiveTigerGeneral[2]  // 取出数组中下标为2的数据

// 取出数组中某一段子序列
let items = fiveTigerGeneral[1...3]  // 一次取出张飞、赵云和马超

// 使用for...in循环遍历整个数组
for item in fiveTigerGeneral {
    print(item)
}

// 使用forEach遍历整个数组
fiveTigerGeneral.forEach { (tiger) in
    print(tiger)
}
(3)、往数组中添加元素

  跟访问数组中的元素一样,往数组中添加元素的方式也有很多种,具体使用哪种方式,取决于你想把新元素添加到数组的什么位置。如果你只想把新元素添加到数组的末尾,直接使用append()方法即可;如果你想把新元素添加到数组指定的位置,应该使用insert(, at: )方法:

// 在数组末尾添加元素
fiveTigerGeneral.append("刘备")  // 将新元素刘备添加到数组末尾

// 将新元素添加到数组指定的位置
fiveTigerGeneral.insert("诸葛亮", at 1)  // 在数组索引为1的位置添加新元素诸葛亮
(4)、从数组中删除元素

  同样,从数组中删除一个元素的姿势也有好几种,这同样取决于你希望删除数组中哪个位置的元素。比如说,如果你想删除数组中第一个元素,可以使用removeFirst()方法;如果你想删除数组末尾的元素,可以使用removeLast()方法;如果你想删除数组中指定位置的元素,可以使用remove(at: )方法;如果你想把数组情况,可以使用removeAll()方法:

// 删除素组最后一个元素
fiveTigerGeneral.removeLast()

// 删除数组第一个元素
fiveTigerGeneral.removeFirst()

// 删除数组索引位置为1的元素
fiveTigerGeneral.remove(at: 1)

// 清空整个数组
fiveTigerGeneral.removeAll()

  数组的用途非常广泛,除了日常的基本存储之外,还可以用来实现其它复杂的数据结构,比如说栈、队列、堆,以及哈希表等等。

二、链式存储数据结构

  在链式存储结构中,每个数据元素不仅仅要存储数据信息,还需要存储与上一个或者下一个元素之间的关系。通常情况下,我们称链式存储结构中的元素为结点。结点一般包含两部分信息,其中存储数据元素信息的部分被称之为数据域,存储直接后继或者前驱的部分为指针域,指针域中存储的信息被称之为指针或者链。

  链表又分为单链表和双链表,其中单链表的指针域存储的是下一个结点的信息,而双链表的指针域不仅存储有下一个结点的信息,还有上一个结点的信息。单链表和双链表结点的示意图如下图所示:

这里写图片描述

  上图中的结点S和N均为单链表结点,其中结点N为单链表中的尾结点,由于它不指示任何结点,因此指针域为空。而结点D为双链表中的结点,其指针域不光指示下一个结点的信息,还指示上一个结点的信息。单链表结构在Swift中的表示如下:

class LinkedList<T> {

    // 单链表结点中的数据域
    var item: T?

    // 单链表中结点的指针域(指示下一个结点的信息)
    var next: LinkedList<T>?
}

  这个只是单链表结点的简单描述,完整的实现将会在后面的系列博客中展现。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值