feat(pointer): 实现双向链表数据结构和基本操作 实现完整的双向链表功能,包括节点定义、链表结构体以及核心操作方法: - Append: 在链表末尾添加节点 - Length: 获取链表长度 - GetIndexNode: 根据索引获取节点 - GetAt: 根据索引获取值 - Insert: 在指定位置插入节点 - Remove: 删除指定位置节点 - Print: 打印链表内容 更新README文档,添加链表实现代码示例和说明,并优化drawio图表。 ```
3.3 KiB
3.3 KiB
指针
陷阱 2:指针指向栈变量的地址逃逸
Go 编译器会自动处理,通常无需担心:
func getPtr() *int {
v := 10
return &v // v 虽然是局部变量,但 Go 会自动提升到堆
}
作业: 实现链表节点和基本操作
package main
import "fmt"
type Node struct {
Value int
Previous *Node // 指向前一个节点
Next *Node // 指向下一个节点
}
type LinkedList struct {
Head *Node
}
// TODO: 实现以下方法
// Append 在链表末尾添加节点
func (l *LinkedList) Append(value int) {
node := &Node{
Value: value,
}
if l.Head == nil {
l.Head = node
return
}
// 遍历链表找到最后一个节点(没有下一个指向), 然后将新节点添加到末尾
current := l.Head
for current.Next != nil {
current = current.Next
}
current.Next = node
node.Previous = current
}
func (l *LinkedList) Length() int {
count := 0
current := l.Head
for current.Next != nil {
count++
current = current.Next
}
return count + 1
}
// GetAt 获取指定位置的值
func (l *LinkedList) GetIndexNode(index int) *Node {
if index < 0 || index >= l.Length() {
return nil
}
current := l.Head
for range index {
current = current.Next
}
return current
}
// GetAt 获取指定位置的值
func (l *LinkedList) GetAt(index int) (int, bool) {
current := l.GetIndexNode(index)
if current == nil {
return 0, false
}
return current.Value, true
}
// Insert 在指定位置插入节点
func (l *LinkedList) Insert(index int, value int) bool {
node := &Node{
Value: value,
}
// 开始和结束之间的位置
if index < 0 || index > l.Length() {
return false
}
// // 插入到开头
// if index == 0 {
// node.Next = l.Head
// l.Head = node
// return true
// }
// // 找到索引的前置节点
// current := l.Head
// for i := 0; i < index-1; i++ {
// current = current.Next
// }
current := l.GetIndexNode(index - 1)
// 将新节点插入到当前节点和下一个节点之间,
// 需要把原来的值 挪到后面,
node.Next = current.Next
// 把前面的值指向新的节点
current.Next = node
return true
}
// Remove 删除指定位置的节点
func (l *LinkedList) Remove(index int) bool {
if index < 0 || index >= l.Length() {
return false
}
// 删除开头的节点,后面的节点自动升级为新的头节点
if index == 0 {
l.Head = l.Head.Next
return true
}
current := l.GetIndexNode(index - 1)
// 将前一个节点的Next指向要删除节点的下一个节点, 通过Next的Next 来跳过要删除的节点
current.Next = current.Next.Next
return true
}
// Print 打印整个链表
func (l *LinkedList) Print() {
for current := l.Head; current != nil; current = current.Next {
fmt.Print(current.Value)
if current.Next != nil {
fmt.Print(" -> ")
}
}
fmt.Println()
}
func main() {
list := &LinkedList{}
list.Append(10)
list.Append(20)
list.Append(30)
list.Print() // 输出: 10 -> 20 -> 30
list.Insert(1, 15)
list.Print() // 输出: 10 -> 15 -> 20 -> 30
value, ok := list.GetAt(2)
fmt.Println("位置2的值:", value, ok) // 20 true
list.Remove(1)
list.Print() // 输出: 10 -> 20 -> 30
fmt.Println("链表长度:", list.Length())
fmt.Println(list.GetIndexNode(1).Previous.Value)
}
