diff --git a/day04/pointer/README.md b/day04/pointer/README.md index a114734..32aa3d1 100644 --- a/day04/pointer/README.md +++ b/day04/pointer/README.md @@ -13,4 +13,163 @@ func getPtr() *int { ![alt text](image.png) -## 作业: 实现链表节点和基本操作 \ No newline at end of file +## 作业: 实现链表节点和基本操作 + + +```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) +} +``` \ No newline at end of file diff --git a/day04/pointer/link_list.drawio b/day04/pointer/link_list.drawio index b2aaa0b..ea13a17 100644 --- a/day04/pointer/link_list.drawio +++ b/day04/pointer/link_list.drawio @@ -1,27 +1,39 @@ - + - + - + - + - - + + - - + + - + + + + + + + + + + + + + diff --git a/day04/pointer/main.go b/day04/pointer/main.go new file mode 100644 index 0000000..a16a6e3 --- /dev/null +++ b/day04/pointer/main.go @@ -0,0 +1,155 @@ +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) +}