# Swift - 链表

### Swift 实现

``````/// 链表节点类
public class ListNode<T> {
var value: T  // 值
var next: ListNode<T>? = nil // 下一个节点
weak var previous: ListNode<T>? = nil
init(value: T) {
self.value = value

}
}

/// 链表类
fileprivate var head: ListNode<T>? // 链表的头
private var tail: ListNode<T>?    // 链表的尾

public var isEmpty: Bool {
}

public var first: ListNode<T>? {
}

public var last: ListNode<T>? {
return tail
}

public func append(node: ListNode<T>) {
if let tailNode = tail {
tailNode.next = node
//            node.previous = tailNode
}else {
}
tail = node
}

public func append(value: T) {
let newNode = ListNode<T>.init(value: value)

if let tailNode = tail {
tailNode.next = newNode
newNode.previous = tailNode
}else {
}
tail = newNode
}

/// node节点后插入值为val的节点
/// - Parameter node: 目标节点啊
/// - Parameter val: 插入的节点的值
func insert(node: ListNode<T>, val: T) {
let newNode = ListNode<T>.init(value: val)
newNode.next = node.next
node.next = newNode
}

public func nodeAt(index: Int) -> ListNode<T>? {
guard index >= 0 else {
return nil
}
var i = index
while node != nil {
if i == 0 {
return node
}
node = node?.next
i -= 1
}
return nil
}

public func removeAll() {
self.tail = nil
}

/// 删除一个节点（单向链表）
/// - Parameter node: 要删除的节点
/// 当需要删除一个节点p时，只需要将p的前一个节点的next赋为p->next,但是由于是单向的，只知道p，无法知道p前一个节点，所以需要转换思路。将p下一个的节点覆盖到p节点即可，这样就等效于将p删除了。
func deleteNode(node: ListNode<T>) {
if let next = node.next {
node.value = next.value
node.next = next.next
}else {
self.pop()
}

}

public func remove(node: ListNode<T>) -> T {
let prev = node.previous
let next = node.next

if let prev = prev {
prev.next = next
} else {
}
next?.previous = prev

if next == nil {
tail = prev
}

node.previous = nil
node.next = nil

return node.value
}

/// 去掉最后一个节点
public func pop() -> T? {

/// 存在最后一个节点
if let last = tail {
/// 存在最后一个节点的前一个节点
if let lp = last.previous {
lp.next = nil
tail = lp
}else {/// 不存在
tail = nil
}
}
tail?.previous = nil
tail?.next = nil
return tail?.value
}

/// 找到循环链表的一个相同节点
///
/// - Returns: <#return value description#>
func fineMeetNode() -> ListNode<T>? {
guard let h = head else {
return nil
}
var fast: ListNode<T>? = h
var slow: ListNode<T>? = h
while (fast?.value != nil && fast?.next?.value != nil) {   //两个变量赛跑，找出相遇的节点
fast = (fast?.next?.next)!
slow = slow?.next!
if (fast!.value == slow!.value) {
return slow
}
}
return nil
}

/// 找到循环链表的入口
///
/// - Returns: <#return value description#>
func findCycleEntrance() -> ListNode<T>? {
guard var meetNode = self.fineMeetNode() else {
return nil
}
meetNode = meetNode.next!
}
return meetNode
}
}

``````

``````let dogbreeds = LinkedList<String>()

let Bulldog = ListNode.init(value: "Bulldog")
let Beagle = ListNode.init(value: "Beagle")
let Husky = ListNode.init(value: "Husky")

dogbreeds.append(node: d)
dogbreeds.append(node: Bulldog)
dogbreeds.append(node: Beagle)
dogbreeds.append(node: Husky)
dogbreeds.append(node: Bulldog)

dogbreeds.nodeAt(index: 0)
dogbreeds.nodeAt(index: 0)?.value == dogbreeds.nodeAt(index: 4)?.value
dogbreeds.nodeAt(index: 2)
dogbreeds.nodeAt(index: 3)

let a = dogbreeds.fineMeetNode()?.value
let a1 = dogbreeds.findCycleEntrance()?.value

let b = dogbreeds.hsaCycle()
``````

### 判断是否是循环链表：

• 1、 在节点ListNode中增加一个域，用于记录此节点是否已经被访问,如下ListNode中被注释掉代码。此方法简单，能找出环开始的节点，但是增加了链表的开销。如果链表非常大 则需要十分大的内存来保存此域。
``````func hsaCycle() -> Bool {

return false
}
if self.isVisit == false {
self.isVisit = true
}else {
return true
}
}
return false
}
``````
• 2、使用两个变量赛跑，一个变量走两步/次，一个变量走一步/次。 如果有环则两个变量必定会相逢，其中快的变量比慢的变量多走一圈。此算法 如果链表的环非常大 则需要较大的遍历时间。此算法同时也能找出环开始的地方

``````/// 找到循环链表的一个相同节点
///
/// - Returns: <#return value description#>
func fineMeetNode() -> ListNode<T>? {
guard let h = head else {
return nil
}
var fast: ListNode<T>? = h
var slow: ListNode<T>? = h
while (fast?.value != nil && fast?.next?.value != nil) {   //两个变量赛跑，找出相遇的节点
fast = (fast?.next?.next)!
slow = slow?.next!
if (fast!.value == slow!.value) {
return slow
}
}
return nil
}

/// 找到循环链表的入口
///
/// - Returns: <#return value description#>
func findCycleEntrance() -> ListNode<T>? {
guard var meetNode = self.fineMeetNode() else {
return nil
}
meetNode = meetNode.next!
}
return meetNode
}
``````

### 删除链表中倒数第n个节点

`1->2->3->4->5, n=2。返回 1->2->3->5`

``````/// 打印协议
extension LinkedList: CustomStringConvertible where T: CustomStringConvertible {
public var description: String {
/// 头节点

var result: String = ""

/// 当前节点不等于nil
result += "->"
}
}
return result
}
}

/// 移除倒数第n个节点
extension LinkedList where T == Int {

func removeNthFromEnd(head: ListNode<T>?, _ n: Int) -> ListNode<T>?{
return nil
}

let dummy = ListNode<Int>.init(value: 0)

var prev: ListNode? = dummy
var post: ListNode? = dummy
/// 设置后一个节点的初始位置
for _ in 0..<n {
post = post?.next
}

/// 同时移动前后节点
while post != nil, post?.next != nil {
prev = prev?.next
post = post?.next
}

// 删除节点
prev?.next = prev?.next?.next

return dummy.next
}
}

ll.append(value: 1)
ll.append(value: 2)
ll.append(value: 3)
ll.append(value: 4)
ll.append(value: 5)
let rrr = ll.description

// 结果： "1->2->3->5"

``````

### 单链表翻转（递归实现）

``````/// 翻转链表(单向链表翻转)
func reverse(head: ListNode<T>?) -> ListNode<T>? {
}

}
``````

#### 步骤解析

1、找到最后一个节点

`a -> b -> c -> d -> e -> nil`

`head?.next.next = head`

newHeader = `e -> nil`

self = `a -> b -> c -> d -> e -> d -> e -> d -> e...`

newHeader = `e -> d -> e -> d -> e ....`

2.1、断链：`head?.next = nil`

self = `a -> b -> c -> d -> nil`

newHeader = `e -> d -> nil`

self = `a -> b -> c -> d -> nil`

newHeader = `e -> d -> nil`

self = `a -> b -> c -> d -> c -> d -> c -> d -> c...`

newHeader = `e -> d -> c -> d -> c ....`

3.1、断链：`head?.next = nil`

self = `a -> b -> c -> nil`

newHeader = `e -> d -> c -> nil`

self = `a -> b -> nil`

newHeader = `e -> d -> c -> b -> nil`

self = `a -> b -> a -> b -> a...`

newHeader = `e -> d -> c -> b -> a -> b -> a ....`

3.1、断链：`head?.next = nil`

self = `a -> nil`

newHeader = `e -> d -> c -> b -> a -> nil`