- 前言
- Go 与操作系统
- Go 内部机制
- Go 基本数据类型
- 4 组合类型的使用
- 5 数据结构
- 6 Go package 中不为人知的知识
- 7 反射和接口
- 8 Go UNIX 系统编程
- 08.1 关于 UNIX 进程
- 08.2 flag 包
- 8.2 flag 包
- 08.3 io.Reader 和 io.Writer 接口
- 08.4 bufio 包
- 08.5 读取文本文件
- 08.6 从文件中读取所需的数据量
- 08.7 为什么我们使用二进制格式
- 08.8 读取 CSV 文件
- 08.9 写入文件
- 08.10 从磁盘加载和保存数据
- 08.11 再看strings包
- 08.12 关于bytes包
- 08.13 文件权限
- 08.14 处理 Unix 信号
- 08.15 Unix 管道编程
- 08.16 遍历目录树
- 08.17 使用 ePBF
- 08.18 关于 syscall.PtraceRegs
- 08.19 跟踪系统调用
- 08.20 User ID 和 group ID
- 08.21 其他资源
- 08.22 练习
- 08.23 总结
- 9 并发 Goroutines、Channel 和 Pipeline
- 10 Go 并发-进阶讨论
- 11 代码测试、优化及分析
- 12 Go 网络编程基础
- 13 网络编程 - 构建服务器与客户端
05.5.1 Go 语言实现链表
Go 语言实现链表
链表相关实现的 Go 源文件是 linkedList.go
,我们将分为五个部分来介绍。
linkedList.go
中的第一个代码段如下:
package main
import (
"fmt"
)
type Node struct {
Value int
Next *Node
}
var root = new(Node)
在这部分代码中,我们定义了用作链表节点的 Node
结构类型和保存链表第一个元素的全局变量 root
,在代码的其他任何地方我们都能访问这个变量。
linkedList.go
的第二部分是如下的 Go 代码:
func addNode(t *Node, v int) int {
if root == nil {
t = &Node{v, nil}
root = t
return 0
}
if v == t.Value {
fmt.Println("Node already exists:", v)
return -1
}
if t.Next == nil {
t.Next = &Node{v, nil}
return -2
}
return addNode(t.Next, v)
}
依据工作原理,链表通常不含重复的项。此外,如果不是有序链表,新的节点通常会被添加在链表的尾部。
因此,addNode()
函数的功能就是向链表中添加新的节点。这个实现中使用 if
语句检查了三种不同的情况。第一种情况,检查要处理的链表是否为空。第二种情况,检查将要插入的值是否已经存在。第三种情况,检查是否已经到达了链表的末端,这时,使用 t.Next = &Node{v, nil}
将含有给定值的新节点加入链表的末端。如果所有的情况都不满足,则使用 return addNode(t.Next, v)
对链表中下一个节点调用 addNode()
,重复上面的过程。
linkedList.go
程序的第三个代码片段包含了 traverse()
函数的实现:
func traverse(t *Node) {
if t == nil {
fmt.Println("-> Empty list!")
return
}
for t != nil {
fmt.Printf("%d -> ", t.Value)
t = t.Next
}
fmt.Println()
}
linkedList.go
的第四部分如下:
func lookupNode(t *Node, v int) bool {
if root == nil {
t = &Node{v, nil}
root = t
return false
}
if v == t.Value {
return true
}
if t.Next == nil {
return false
}
return lookupNode(t.Next, v)
}
func size(t *Node) int {
if t == nil {
fmt.Println("-> Empty list!")
return 0
}
i := 0
for t != nil {
i++
t = t.Next
}
return i
}
这一部分包含了两个非常方便的函数——lookupNode()
和 size()
的实现。前一个函数检查链表中是否存在给定的元素,后一个函数返回链表的大小,也就是链表中节点的数量。
lookupNode()
函数实现背后的逻辑很容易理解:依次访问单向链表中所有的元素来查找你想要的值。如果你从头到尾都没找到想要的值,那就说明链表中没有这个值。
linkedList.go
的最后一部分包含 main()
函数的实现:
func main() {
fmt.Println(root)
root = nil
traverse(root)
addNode(root, 1)
addNode(root, -1)
traverse(root)
addNode(root, 10)
addNode(root, 5)
addNode(root, 45)
addNode(root, 5)
addNode(root, 5)
traverse(root)
addNode(root, 100)
traverse(root)
if lookupNode(root, 100) {
fmt.Println("Node exists!")
} else {
fmt.Println("Node does not exist!")
}
if lookupNode(root, -100) {
fmt.Println("Node exists!")
} else {
fmt.Println("Node does not exist!")
}
}
执行 linkedList.go
将生成如下的输出:
$ go run linkedList.go
&{0 <nil>}
-> Empty list!
1 -> -1 ->
Node already exists: 5
Node already exists: 5
1 -> -1 -> 10 -> 5 -> 45 ->
1 -> -1 -> 10 -> 5 -> 45 -> 100 ->
Node exists!
Node does not exist!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论