链表
链表是数据结构中经常会用到的一种数据结构,是指一串数据项,每一个数据项称之为节点(Node)。
链表主要有两种:
单链表,链表中的每个节点只有向后的索引
双链表,链表除了向后的索引之外,还有指向前一个的索引
定义节点
链表是有节点组成的,首先定义节点的数据结构: Node
- 首先将节点定义为一个类 - Node
- 添加值,并添加一个初始化方法
- 要有一个指针 next 指向下一个节点,注意这个指针必须是可选类型,因为链表最后的一个 Node 的 next 指针不指向任何 Node
1 | public class Node { |
如果是双向链表,还需要定义 previous 指针:
1 | public class Node { |
这里 previous 使用 weak 是为了防止循环引用
定义链表
定义链表,有两个节点 head 和 tail
1 |
|
空链表
1 | public var isEmpty: Bool { |
添加测试代码:
1 | //测试 |
添加节点
1 |
|
说明:
- 首先根据传入的 value, 创建一个新的节点
- 如果 tail 不为 nil,就说明当前的链表内有内容,所以执行插入操作
- 插入操作:newNode 的 previous 指向 tail,tail 的 next 指针指向 newNode,并且设置 newNode 为新的 tail
- 如果 tail 为 nil, 就说明当前链表为空链表,直接设置 head 为 newNode 就可以了,然后设置 tail 为 newNode
1 | //测试 |
输出链表
当我们学会插入节点之后,第一时间就行看看链表中的内容。目前如果只是简单的 print(link) 的话是不能打印出处链表的信息的,为了实现输出链表信息,做如下操作:
1 |
|
说明:
- 首先为 LinkedList 声明 extension,然后实现 CustomStringConvertible 协议,这个协议要求你实现 computed property description:String
- 所以在 extension 内部,声明可计算属性 description,类型为 String,并且该属性是只读属性
- 然后在内容通过对 linkedList 的遍历以及字符串拼接,返回需要输出的链表格式
测试:
1 | let link1 = LinkedList() |
playground 自动显示
查找节点
根据输入链表中 node 的位置返回 node object
1 | public func nodeAt(_ index: Int) -> Node? { |
说明:
- 首先剔除 index 为负数的情况,返回 nil
- 接着通过 node != nil 来进行循环,然后通过 index 自减是否为零来进行判断
测试:
1 | func testNodeAt () { |
删除所有节点
1 | public func removeAll() { |
测试:
1 | func testRemoveAll () { |
删除指定节点
1 | public func remove(_ node: Node) -> Int { |
测试:
1 | func testRemove () { |