链表
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。
实现一个链表
链表由一系列的节点组成,所以我们要先去实现一个节点(Node),我们准备做一个双向链表,所以节点由值(value),前(prev),后(next)节点组成:
class Node<T> {
var value: T
var next: Node? = nil //下一个指向的节点
weak var prev: Node? = nil //上一个指向的节点
public init(_ value: T) {
self.value = value
}
}
下面我们去实现一个基本的链表:
private var head: Node<T>?
var isEmpty: Bool {
return head == nil
}
var first: Node<T>? {
return head
}
var last: Node<T>? {
if var node = head {
while let next = node.next {
node = next
}
return node
}
return nil
}
var count: Int {
if var node = head {
var nodeCount = 1
while let next = node.next {
node = next
nodeCount += 1
}
return nodeCount
}
return 0
}
链表还应该有基本的增删改查等功能,原理都是改变节点(Node)的前后指向,基于这个思路,我们再完善一下:
func append(_ value: T) -> Void {
let newNode = Node(value)
if let lastNode = last {
newNode.prev = lastNode
lastNode.next = newNode
} else {
head = newNode
}
}
func nodeAtIndex(index: Int) -> Node<T>? {
var node = head
if index >= 0 {
var count = index
while count > 0 {
node = node?.next
count -= 1
}
return node
}
return head
}
func subScript(index: Int) -> T? {
if let value = nodeAtIndex(index: index)?.value {
return value
}
return nil
}
func nodesBeforeAndAfter(index: Int) -> (Node<T>? , Node<T>?) {
let node = nodeAtIndex(index: index)
return (node?.prev , node?.next )
}
func insert(value: T, atIndex index: Int) -> Void {
if index >= count , index < 0{ // 索引错误
print("index error")
return
}
let (before, _) = nodesBeforeAndAfter(index: index)
let node = nodeAtIndex(index: index)
let newNode = Node<T>(value)
newNode.next = node
newNode.prev = before
before?.next = newNode
if before == nil {
head = newNode
}
}
func replace(value: T, atIndex index: Int) -> Void {
if index >= count , index < 0 { // 索引错误
print("index error")
return
}
let (before, after) = nodesBeforeAndAfter(index: index)
let newNode = Node<T>(value)
newNode.next = after
newNode.prev = before
before?.next = newNode
after?.prev = newNode
if before == nil {
head = newNode
}
}
func printNode() -> Void {
var node = head
while node != nil {
print(node?.value ?? "none")
node = node?.next
}
}
func removeAll() -> Void {
head = nil
}
func remove(node: Node<T>) -> Void {
let prev = node.prev
let next = node.next
if prev != nil {
prev?.next = next
}
next?.prev = prev
node.prev = nil
node.next = nil
}
func remove(index: Int) -> Void {
guard let node = nodeAtIndex(index: index) else {
return
}
remove(node: node)
}