链表 - 设计链表
这次我们不以力扣上的题为例了,难度不大,设计一个单链表的接口。需要实现如下功能
- 获取第n个节点的值
- 头部插入节点
- 尾部插入节点
- 第n个节点插入节点
- 删除第n个节点
注意:这个n是真实的下标,从0开始的。
为什么加上虚拟头节点,上一篇文章已经说了,就是为了方便统一操作。
这道题实现起来难度不大,主要是理清楚
- 虚拟头节点的作用
- 下标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()
}