鏈表是實現線性表的鏈式存儲結構的一種數據結構,鏈表根據結定義不一樣也有幾個種類,分別爲:node
如下的實例代碼,都是以單鏈表爲例的。數組
這篇文章的主要內容bash
鏈表數據結構
用一組任意的存儲單元存儲數據元素,這組存儲單元能夠是連續的,也能夠是不連續的。數據元素間的邏輯順序是經過結點中的指針域來實現。app
結點函數
存儲數據元素信息的域稱爲數據域,把存儲後繼位置或前驅結點的域稱爲指針域。這兩部分就是鏈表中的一個節點。post
結點的基本結構:性能
class LinkedListNode {
var value: Int
var next: LinkedListNode?
public init(_ value: Int) {
self.value = value
self.next = nil
}
}
複製代碼
鏈表的接本結構:ui
class LinkedList {
var head: LinkedListNode? // 頭結點
var tail: LinkedListNode? // 尾結點
}
複製代碼
先在已經定義好了鏈表及結點的基本結構了,下面咱們能夠對鏈表作一些常見的操做。spa
func appendToTail(_ value: Int) {
let newNode = LinkedListNode(value)
if let last = tail {
last.next = newNode
tail = last.next
} else {
head = newNode
tail = head
}
}
複製代碼
func appendToHead(_ value: Int) {
let newNode = LinkedListNode(value)
if let first = head {
newNode.next = first
head = newNode
} else {
head = newNode
tail = head
}
}
複製代碼
// 給鏈表增長了一個長度屬性
var length: Int {
get {
var num = 0
var temp: LinkedListNode? = head
while let node = temp {
num += 1
temp = node.next
}
return num
}
}
func appned(_ value: Int, _ index: Int) {
if length == 0 {
// 鏈表自己爲空,直接添加
appendToHead(value)
} else if index == 0 {
// 插入到頭結點位置
let newNode = LinkedListNode(value)
newNode.next = head
head = newNode
} else if index < length && index > 0 {
// 找到須要插入位置的前一個結點
let newNode = LinkedListNode(value)
var temp = 1
var tempNode: LinkedListNode? = head
while let node = tempNode {
if temp == index {
newNode.next = node.next
node.next = newNode
break
}
tempNode = tempNode?.next
temp += 1
}
}
}
複製代碼
利用尾插法直接將數組元素插入到鏈表末端
init(array: [Int]) {
array.forEach { appendToTail($0) }
}
複製代碼
func remove(at index: Int) {
// 鏈表爲空
if length == 0 {
return
} else if index == 0 {
head = head?.next
} else if index < length && index > 0 {
var tempNode: LinkedListNode?
var j = 0
var tempList: LinkedListNode? = head
while tempList?.next != nil && j < index-1 {
tempList = tempList?.next
j += 1
}
tempNode = tempList?.next
tempList?.next = tempNode?.next
}
}
複製代碼
// 查找某個結點
func node(at index: Int) -> LinkedListNode? {
if length == 0 {
return nil
} else if index >= 0 && index < length {
var tempNode = head
var j = 0
while tempNode?.next != nil && j < index {
tempNode = tempNode?.next
j += 1
}
return tempNode
}
return nil
}
// 根據值查找
func nodes(_ value: Int) -> [LinkedListNode] {
var result: [LinkedListNode] = []
var tempNode = head
while let node = tempNode {
if node.value == value {
result.append(node)
}
tempNode = node.next
}
return result
}
複製代碼
func reverse(_ head: LinkedListNode?) -> LinkedListNode? {
if head == nil || head?.next == nil {
return head
}
// 遞歸找到最後一個結點
let newHead = reverse(head?.next)
// 將最後一個結點前一個結點反轉
head?.next?.next = head
// 斷開最後一個結點
head?.next = nil
self.head = newHead
return newHead
}
複製代碼
過程說明:
// 打印鏈表
func printSelf() {
var tempNode = head
while let node = tempNode {
print(node.value)
tempNode = tempNode?.next
}
}
func map(transform: (Int) -> Int) -> LinkedList {
let result = LinkedList()
var tempNode = head
while let node = tempNode {
result.appendToTail(transform(node.value))
tempNode = node.next
}
return result
}
func filter(predicate: (Int) -> Bool) -> LinkedList {
let result = LinkedList()
var tempNode = head
while let node = tempNode {
if predicate(node.value) {
result.appendToTail(node.value)
}
tempNode = node.next
}
return result
}
複製代碼
結合上篇線性表的順序存儲結構與單鏈表結構進行對比:
存儲方式
時間性能
空間性能