链表 - 设计链表

106 阅读2分钟

链表 - 设计链表

这次我们不以力扣上的题为例了,难度不大,设计一个单链表的接口。需要实现如下功能

  1. 获取第n个节点的值
  2. 头部插入节点
  3. 尾部插入节点
  4. 第n个节点插入节点
  5. 删除第n个节点

注意:这个n是真实的下标,从0开始的。

image.png 为什么加上虚拟头节点,上一篇文章已经说了,就是为了方便统一操作。

这道题实现起来难度不大,主要是理清楚

  1. 虚拟头节点的作用
  2. 下标n具体指的是什么
// LinkedList 单链表
type LinkedList struct {
    val  int         // 节点所代表的值
    size int         // 整个链表中所有的节点数,头节点 - 虚拟头节点需要存
    next *LinkedList // 下一个节点的地址
}

func NewLinkedList() *LinkedList {
    return &LinkedList{}
}

// Get 获取下标为 index 的节点数据
// index 是从 0 开始的
// 比如: size = 5, index 最大应该是 4
func (list *LinkedList) Get(index int) int {
    node := list.Index(index)
    if node == nil {
            return -1
    }
    return node.val
}

// AddAtHead 向头部插入节点
// 也可以理解成向下标为 0 的位置插入节点
func (list *LinkedList) AddAtHead(val int) {
    list.AddAtIndex(0, val)
}

// AddAtTail 向尾部插入节点
// 也可以理解成向下标为 list.size 的位置插入节点
func (list *LinkedList) AddAtTail(val int) {
    list.AddAtIndex(list.size, val)
}

// AddAtIndex 向尾部插入节点
// 也可以理解成向下标为 index 的位置插入节点
func (list *LinkedList) AddAtIndex(index int, val int) {
    newNode := LinkedList{val: val}
    if index == 0 { // 向头部插入节点
        newNode.next = list.next
        list.next = &newNode
    } else if index == list.size { // 向尾部插入节点
        lastNode := list.Index(index - 1)
        if lastNode == nil {
                return
        }
        lastNode.next = &newNode
    } else { // 向中间节点插入节点
        preNode := list.Index(index - 1)
        if preNode == nil {
                return
        }
        newNode.next = preNode.next
        preNode.next = &newNode
    }
    list.size++
}

// DeleteAtIndex 删除下标为 index 的节点
func (list *LinkedList) DeleteAtIndex(index int) {
    if index < 0 || index > list.size || list.size == 0 {
        return
    }
    if index == 0 { // 删除头部节点
        list.next = list.next.next
    } else if index == list.size { // 删除尾部节点
        preNode := list.Index(index)
        if preNode == nil {
            return
        }
        preNode.next = nil
    } else { // 删除中间节点
        preNode := list.Index(index - 1)
        if preNode == nil {
            return
        }
        preNode.next = preNode.next.next
    }
    list.size--
}

// Index 查找下标为 index 的节点并返回
func (list *LinkedList) Index(index int) *LinkedList {
    if index < 0 || index > list.size {
        return nil
    }
    current := list.next
    for i := 0; i < index; i++ {
        current = current.next
    }
    return current
}

// Print 输出链表数据
func (list *LinkedList) Print() {
    current := list.next
    for i := 0; i < list.size; i++ {
        fmt.Print(current.val, " ")
        current = current.next
    }
    fmt.Println()
}