前面实现了单向链表,在此基础上实现了双向链表。
双向链表增加了prev结点,add、remove、node方法做了更改。
class LinkedList<T> {
class Node<E> {
// 节点内容
var element: E?
// prev节点
var prev: Node<E>?
// next节点
var next: Node<E>?
init(element: E? = nil, prev: Node<E>? = nil, next: Node<E>? = nil) {
self.element = element
self.prev = prev
self.next = next
}
}
// 链表长度
var size: Int = 0
// 头节点
var head: Node<T>?
// 尾节点
var tail: Node<T>?
// MARK: 清空
func clear() {
size = 0
head = nil
tail = nil
}
func isEmpty() -> Bool {
return size == 0
}
// MARK: 获取index位置对应节点对象
func get(_ index: Int) -> T? {
// 最好:O(1) 最坏:O(n) 平均:O(n)
return node(index)?.element
}
// MARK: 设置index位置对应节点对象
@discardableResult
func set(_ index: Int, _ element: T) -> T? {
// 最好:O(1) 最坏:O(n) 平均:O(n)
let node = node(index)
let old = node?.element
node?.element = element
return old
}
// MARK: 在末尾位置添加节点对象
func add(_ element: T) {
add(size, element)
}
// MARK: 在index位置添加节点对象
func add(_ index: Int, _ element: T) {
// 最好:O(1) 最坏:O(n) 平均:O(n)
if !rangeCheckForAdd(index) {
return
}
if index == size { // 在尾部添加
let prev = tail
tail = Node(element: element, prev: prev, next: nil)
if prev == nil { // 链表添加的第一个元素
head = tail
} else {
prev?.next = tail
}
} else {
let next = node(index)
let prev = next?.prev // 这里不要写prev = node(index - 1),一是重复遍历,二是index == 0会报错
let current = Node(element: element, prev: prev, next: next)
next?.prev = current
if prev == nil { // index == 0
head = current
} else {
prev?.next = current
}
}
size += 1
}
// MARK: 删除index位置对应节点对象
@discardableResult
func remove(_ index: Int) -> T? {
// 最好:O(1) 最坏:O(n) 平均:O(n)
if !rangeCheck(index) {
return nil
}
let current = node(index)
let prev = current?.prev
let next = current?.next
if prev == nil { // index == 0
head = next
} else {
prev?.next = next
}
if next == nil { // index == size - 1
tail = prev
} else {
next?.prev = prev
}
size -= 1
return current?.element
}
// MARK: 获取index位置对应的节点对象
@discardableResult
private func node(_ index: Int) -> Node<T>? {
if !rangeCheck(index) {
return nil
}
if index < (size >> 1) {
var node = head
for _ in 0..<index {
node = node?.next
}
return node
} else {
var node = tail
for i in stride(from: index - 1, to: size, by: -1) {
print(i)
node = node?.prev
}
return node
}
}
func rangeCheck(_ index: Int) -> Bool {
let enable = index >= 0 && index < size
if !enable {
print("### ERROR ### \(index) out of bounds. size = \(size)")
}
return enable
}
func rangeCheckForAdd(_ index: Int) -> Bool {
let enable = index >= 0 && index <= size
if !enable {
print("### ERROR ### \(index) out of bounds. size = \(size)")
}
return enable
}
}
加一个LinkedList的扩展,使其遵循Equatable协议,实现indexOf方法,这样以后使用LinkedList的时候就可以不用一定要遵循Equatable协议,例如用链表实现队列等。
extension LinkedList where T: Equatable {
// MARK: 获取节点对象所在位置
@discardableResult
func indexOf(_ element: T) -> Int {
var current = head
for i in 0..<size {
if element == current!.element {
return i
}
current = current?.next
}
return -1
}
}
双向链表 vs 单向链表
双向链表 vs 动态数组