链表的特点和初始化
链表的特点
用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的)
结点
结点(node)
数据域 => 存储元素信息
指针域 => 存储结点的直接后继,也称作指针或链
首元结点 是指链表中存储的第一个数据元素的结点
头结点 是在首元结点之前附设的一个结点,其指针域指向首元结点(非必须)
头指针 是指向链表中第一个结点的指针
单链表特点
- 每个结点中只包含一个指针域
- 单链表是非随机存取的存储结构,要取得第i个数据元素必须从头指针出发,顺链进行寻找,也称为顺序存取的存取结构
官方包链表操作
https://pkg.go.dev/container/list
手动实现单链表部分操作
// 实现单链表一些基础操作
package main
import (
"errors"
"fmt"
)
// 链表结构
type ListNode struct {
Data int
Next *ListNode
}
// 初始化链表头,下面所有操作都基于带头链表
func NewListNode() *ListNode {
return &ListNode{Next: nil}
}
// 获取链表长度
func (l *ListNode) Length() int {
len := 0
for l.Next != nil {
len++
l = l.Next
}
return len
}
// 插入节点
func (l *ListNode) InsertNode(d int) error {
newNode := new(ListNode)
newNode.Data = d
newNode.Next = l.Next
l.Next = newNode
return nil
}
// 删除节点
func (l *ListNode) DelNode(d int) {
if l == nil {
errors.New("Empty List!")
return
}
for l.Next != nil {
if l.Next.Data == d {
l.Next = l.Next.Next
// return 是否全部删除与d相同数据
}
l = l.Next
}
}
// 遍历单链表
func (l *ListNode) ListNode() {
for l.Next != nil {
fmt.Printf("%d", l.Next.Data)
l = l.Next
}
}
// 递归反转单链表
func ReverseList(pHead, node *ListNode) *ListNode {
if node.Next == nil {
pHead.Next = node
return node
}
if n := ReverseList(pHead, node.Next); n != nil {
n.Next = node
node.Next = nil
}
return node
}
// 遍历反转单链表
func (pHead *ListNode) ReverseListV2() {
pReverseHead := pHead
var pNode = pHead.Next
var pPrev *ListNode
for pNode != nil {
pNext := pNode.Next
if pNext == nil {
pReverseHead.Next = pNode
}
pNode.Next = pPrev
pPrev = pNode
pNode = pNext
}
return
}