链表结构定义如下:

// 链表结点
type SinListNode struct {
    next *SinListNode
    val int
}

// 链表结构
type SinLinkedList struct {
    head *SinListNode
    len uint
}

实现的操作有:

  • 单链表结点的创建
  • 获取链表的下一结点
  • 获取结点值
  • 链表的创建
  • 在指定结点后插入结点
  • 在指定结点前插入结点
  • 在链表头部插入结点
  • 在链表尾部插入结点
  • 通过索引查找结点
  • 删除指定结点
  • 链表的打印
  • 链表的翻转
  • 判断链表是否有环
  • 合并两个有序单链表
  • 删除倒数第N个结点
  • 获取链表的中间结点

代码如下:

package main

import "fmt"

/*
单链表的实现
 */


// 链表结点
type SinListNode struct {
    next *SinListNode
    val int
}

// 链表结构
type SinLinkedList struct {
    head *SinListNode
    len uint
}


// 创建结点
func NewListNode(v interface{}) *SinListNode {
    return &SinListNode{nil, v}
}

// 获取链表下一个节点
func (this *SinListNode) GetNext() *SinListNode  {
    return this.next
}

// 获取节点值
func (this *SinListNode) GetValue() int  {
    return this.val
}

// 创建链表
func NewLinkedList() *SinLinkedList  {
    return &SinLinkedList{NewListNode(0), 0}
}


// 在指定节点后面插入节点
func (this *SinLinkedList) InsertAffter(p *SinListNode, v int) bool {
    if nil == p {
        return false
    }
    // 创建一个新节点
    newNode, oldNext := NewListNode(v), p.next
    // 新节点插入到指定节点后,原节点的下一节点插入到新节点的下一节点
    p.next, newNode.next = newNode, oldNext
    this.len++
    return true
}


// 在某个节点前面插入节点
func (this *SinLinkedList) InsertBefore(p *SinListNode, v int) bool {
    if nil == p || p == this.head {
        return false
    }

    cur := this.head.next // 记录当前节点
    pre := this.head // 记录前缀节点

    // 查找p的前缀节点
    for cur != nil {
        if cur == p {
            break
        }
        pre = cur
        cur = cur.next
    }

    if cur == nil {
        return false
    }

    newNode := NewListNode(v)
    pre.next = newNode  // 前缀节点指向新节点
    newNode.next = cur // 新节点指向原来的节点P
    this.len++
    return true
}

// 在链表头部插入节点
func (this *SinLinkedList) InsertToHead(v int) bool {
    return this.InsertAffter(this.head, v)
}

// 在链表尾部插入节点
func (this *SinLinkedList) InsertToTail(v int) bool  {
    cur := this.head

    // 查找尾节点
    for cur.next != nil {
        cur = cur.next
    }
    return this.InsertAffter(cur, v)
}


// 通过索引查找节点
func (this *SinLinkedList) FindByIndex(idx uint) *SinListNode {
    if idx >= this.len {
        return nil
    }
    cur := this.head.next

    // 移动节点值idx位置
    var i uint = 0
    for ; i < idx; i++ {
        cur = cur.next
    }

    return cur
}

// 删除指定结点
func (this *SinLinkedList) DeleteNode(p *SinListNode) bool {
    if p == nil {
        return false
    }
    cur := this.head.next
    pre := this.head

    // 查找p的前驱节点
    for cur != nil {
        if cur == p {
            break
        }
        pre = cur
        cur = cur.next
    }
    // 找不到p节点
    if cur == nil {
        return false
    }
    // p的前驱节点指向p的后继节点
    pre.next = p.next
    p = nil // 释放p节点
    this.len--
    return true
}

// 打印链表
func (this *SinLinkedList) Print() {
    cur := this.head.next
    format := ""
    for cur != nil {
        format += fmt.Sprintf("%+v", cur.GetValue())
        if cur != nil {
            format += "->"
        }
    }
    fmt.Println(format)
}


// 单链表翻转,时间复杂度O(n)
func (this *SinLinkedList)Reverse()  {
    if this.head == nil || this.head.next == nil || this.head.next.next == nil {
        return
    }
    var pre *SinListNode = nil

    cur := this.head.next

    for cur != nil {
        tmp := cur.next
        cur.next = pre
        pre, cur = cur, tmp
    }
    this.head.next = pre
}


// 快慢指针判断链表是否有环
func (this *SinLinkedList) HasCycle() bool {
    if this.head != nil {
        slow := this.head
        fast := this.head

        if fast != nil && fast.next != nil{
            slow = slow.next // 慢指针一次移动一个节点
            fast = fast.next.next  // 快指针一次移动两个节点
            if slow == fast { // 指针相遇证明有环
                return true
            }
        }
    }
    return false
}


// 合并两个有序单链表
func MergeSortedList(l1, l2 *SinLinkedList) *SinLinkedList {
    // 链表1为空直接返回链表2
    if l1 == nil || l1.head == nil || l1.head.next == nil {
        return l2
    }

    // 链表2为空直接返回链表1
    if l2 == nil || l2.head == nil || l2.head.next == nil {
        return l1
    }
    l := &SinLinkedList{head:&SinListNode{}}
    cur := l.head
    // 使用双指针思想进行合并
    curl1 := l1.head.next
    curl2 := l2.head.next

    for curl1 != nil && curl2 != nil {

        if curl1.GetValue() > curl2.GetValue() {
            cur.next = curl2
            curl2 = curl2.next
        }else {
            cur.next = curl1
            curl1 = curl1.next
        }
        cur = cur.next
    }
    if curl1 != nil {
        cur.next = curl1
    }else if curl2!= nil {
        cur.next = curl2
    }
    return l
}

// 删除倒数第N个节点
func (this *SinLinkedList) DeleteBottomN(n int)   {
    if n <= 0 || this.head == nil || this.head.next == nil {
        return
    }
    fast := this.head

    // 查找第N个节点
    for i := 1; i <= n && fast!= nil; i++ {
        fast = fast.next
    }

    if fast == nil {
        return
    }

    slow := this.head
    for fast.next != nil {
        slow = slow.next
        fast = fast.next
    }
    slow.next = slow.next.next
}

// 获取链表的中间节点
func (this *SinLinkedList) FindMiddleNode() *SinListNode  {
    if nil == this.head || this.head.next == nil {
        return nil
    }
    // 链表只有一个元素则直接返回该节点
    if this.head.next.next == nil {
        return this.head.next
    }

    slow, fast := this.head, this.head

    // 使用快慢指针, 快指针移动两个节点,慢指针移动一个节点,当快指针遍历结束,那么慢指针指向的节点为中间节点
    for fast != nil && fast.next != nil {
        slow = slow.next
        fast = fast.next.next
    }
    return slow
}