go20/day04/pointer/README.md
yumaojun03 e802a2e4e9 ```
feat(pointer): 实现双向链表数据结构和基本操作

实现完整的双向链表功能,包括节点定义、链表结构体以及核心操作方法:
- Append: 在链表末尾添加节点
- Length: 获取链表长度
- GetIndexNode: 根据索引获取节点
- GetAt: 根据索引获取值
- Insert: 在指定位置插入节点
- Remove: 删除指定位置节点
- Print: 打印链表内容

更新README文档,添加链表实现代码示例和说明,并优化drawio图表。
```
2026-02-08 10:34:11 +08:00

175 lines
3.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 指针
## 陷阱 2指针指向栈变量的地址逃逸
Go 编译器会自动处理,通常无需担心:
```go
func getPtr() *int {
v := 10
return &v // v 虽然是局部变量,但 Go 会自动提升到堆
}
```
![alt text](image.png)
## 作业: 实现链表节点和基本操作
```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)
}
```