```
feat(pointer): 实现双向链表数据结构和基本操作 实现完整的双向链表功能,包括节点定义、链表结构体以及核心操作方法: - Append: 在链表末尾添加节点 - Length: 获取链表长度 - GetIndexNode: 根据索引获取节点 - GetAt: 根据索引获取值 - Insert: 在指定位置插入节点 - Remove: 删除指定位置节点 - Print: 打印链表内容 更新README文档,添加链表实现代码示例和说明,并优化drawio图表。 ```
This commit is contained in:
parent
676bd68412
commit
e802a2e4e9
@ -13,4 +13,163 @@ func getPtr() *int {
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
## 作业: 实现链表节点和基本操作
|
## 作业: 实现链表节点和基本操作
|
||||||
|
|
||||||
|
|
||||||
|
```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)
|
||||||
|
}
|
||||||
|
```
|
||||||
@ -1,27 +1,39 @@
|
|||||||
<mxfile host="65bd71144e">
|
<mxfile host="65bd71144e">
|
||||||
<diagram id="mRYyQN2MmenF_MetcyJE" name="第 1 页">
|
<diagram id="mRYyQN2MmenF_MetcyJE" name="第 1 页">
|
||||||
<mxGraphModel dx="1134" dy="530" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
|
<mxGraphModel dx="1108" dy="581" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
|
||||||
<root>
|
<root>
|
||||||
<mxCell id="0"/>
|
<mxCell id="0"/>
|
||||||
<mxCell id="1" parent="0"/>
|
<mxCell id="1" parent="0"/>
|
||||||
<mxCell id="4" style="edgeStyle=none;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="2" target="3">
|
<mxCell id="11" style="edgeStyle=orthogonalEdgeStyle;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="2" target="8">
|
||||||
<mxGeometry relative="1" as="geometry"/>
|
<mxGeometry relative="1" as="geometry"/>
|
||||||
</mxCell>
|
</mxCell>
|
||||||
<mxCell id="2" value="Node" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
<mxCell id="2" value="Node<div>current</div>" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||||
<mxGeometry x="120" y="200" width="170" height="60" as="geometry"/>
|
<mxGeometry x="120" y="200" width="170" height="60" as="geometry"/>
|
||||||
</mxCell>
|
</mxCell>
|
||||||
<mxCell id="6" style="edgeStyle=none;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="3" target="5">
|
<mxCell id="6" style="edgeStyle=none;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="3" target="5" edge="1">
|
||||||
<mxGeometry relative="1" as="geometry"/>
|
<mxGeometry relative="1" as="geometry"/>
|
||||||
</mxCell>
|
</mxCell>
|
||||||
<mxCell id="3" value="Node" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
<mxCell id="3" value="Node<div><br></div>" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||||
<mxGeometry x="370" y="200" width="170" height="60" as="geometry"/>
|
<mxGeometry x="590" y="200" width="170" height="60" as="geometry"/>
|
||||||
</mxCell>
|
</mxCell>
|
||||||
<mxCell id="5" value="Node" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
<mxCell id="5" value="Node" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||||
<mxGeometry x="610" y="200" width="170" height="60" as="geometry"/>
|
<mxGeometry x="790" y="200" width="170" height="60" as="geometry"/>
|
||||||
</mxCell>
|
</mxCell>
|
||||||
<mxCell id="7" value="LinkList : 访问效果低,&nbsp; 修改成本低<div><br></div><div>slice: 访问效果高, 不支持修改</div>" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
<mxCell id="7" value="LinkList : 访问效果低,&nbsp; 修改成本低<div><br></div><div>slice: 访问效果高, 不支持修改</div>" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||||
<mxGeometry x="90" y="80" width="270" height="60" as="geometry"/>
|
<mxGeometry x="90" y="80" width="270" height="60" as="geometry"/>
|
||||||
</mxCell>
|
</mxCell>
|
||||||
|
<mxCell id="10" style="edgeStyle=orthogonalEdgeStyle;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="8" target="3">
|
||||||
|
<mxGeometry relative="1" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="8" value="Node<div>new</div>" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="370" y="330" width="170" height="60" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="9" value="" style="endArrow=classic;html=1;" edge="1" parent="1">
|
||||||
|
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||||
|
<mxPoint x="460" y="60" as="sourcePoint"/>
|
||||||
|
<mxPoint x="460" y="170" as="targetPoint"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
</root>
|
</root>
|
||||||
</mxGraphModel>
|
</mxGraphModel>
|
||||||
</diagram>
|
</diagram>
|
||||||
|
|||||||
155
day04/pointer/main.go
Normal file
155
day04/pointer/main.go
Normal file
@ -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)
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user