下面我将详细讲解使用go实现常见的数据结构的完整攻略。
1. 概述
数据结构是计算机程序设计中一个非常重要的概念,常见的有数组、链表、栈、队列、树、图等。本文主要介绍如何使用Go实现常见的数据结构。
2. 数组
数组是最简单、最基本的数据结构之一,它在Go中的实现非常简单,可以用以下代码片段表示:
// 定义一个长度为10的整型数组
var arr [10]int
// 初始化一个长度为5的整型数组
arr2 := [5]int{1, 2, 3, 4, 5}
需要注意的是,数组在定义时必须指定长度,且长度必须是一个常数。
3. 链表
链表是一种动态数据结构,它支持快速插入和删除操作。在Go中实现链表可以使用指针,以下为示例代码:
type Node struct {
data int
next *Node
}
// 初始化一个链表
var head *Node = new(Node)
head.next = nil
// 插入一个节点
newNode := new(Node)
newNode.data = 1
newNode.next = head.next
head.next = newNode
// 遍历链表
for pNode := head.next; pNode != nil; pNode = pNode.next {
fmt.Println(pNode.data)
}
需要注意的是,链表中的数据类型可以是任意类型。
4. 栈
栈是一种后进先出(LIFO)的数据结构,通常用于表达式求值、括号匹配等问题。在Go中可以使用切片(slice)来实现栈,以下为示例代码:
// 定义一个栈结构体
type Stack struct {
data []int
}
// 入栈
func (s *Stack) Push(x int) {
s.data = append(s.data, x)
}
// 出栈
func (s *Stack) Pop() int {
x := s.data[len(s.data)-1]
s.data = s.data[:len(s.data)-1]
return x
}
// 创建一个栈
s := new(Stack)
// 入栈
s.Push(1)
s.Push(2)
s.Push(3)
// 出栈
fmt.Println(s.Pop()) // 输出 3
fmt.Println(s.Pop()) // 输出 2
fmt.Println(s.Pop()) // 输出 1
需要注意的是,使用切片实现的栈需要注意初始容量,以提高性能。
5. 队列
队列是一种先进先出(FIFO)的数据结构,在Go中可以使用切片或链表来实现。以下为示例代码:
// 使用切片实现队列
type Queue struct {
data []int
}
// 入队
func (q *Queue) Enqueue(x int) {
q.data = append(q.data, x)
}
// 出队
func (q *Queue) Dequeue() int {
x := q.data[0]
q.data = q.data[1:]
return x
}
// 使用链表实现队列
type Node struct {
data int
next *Node
}
type Queue struct {
head *Node
tail *Node
}
// 入队
func (q *Queue) Enqueue(x int) {
newNode := new(Node)
newNode.data = x
newNode.next = nil
if q.head == nil {
q.head = newNode
q.tail = newNode
} else {
q.tail.next = newNode
q.tail = newNode
}
}
// 出队
func (q *Queue) Dequeue() int {
x := q.head.data
q.head = q.head.next
return x
}
需要注意的是,在使用链表实现队列时,需要维护队头和队尾指针。
6. 树
树是一种递归结构,它由节点和边组成,每个节点包含一个值和若干棵子树。在Go中可以使用结构体和指针来实现树,以下为示例代码:
// 定义一个二叉搜索树
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
// 插入节点
func (root *TreeNode) Insert(x int) *TreeNode {
if root == nil {
return &TreeNode{Val: x}
}
if x < root.Val {
root.Left = root.Left.Insert(x)
} else if x > root.Val {
root.Right = root.Right.Insert(x)
}
return root
}
// 构造一棵二叉搜索树
root := new(TreeNode)
root.Val = 3
root.Insert(1)
root.Insert(5)
root.Insert(4)
root.Insert(2)
// 中序遍历
var inorderTraversal func(root *TreeNode)
inorderTraversal = func(root *TreeNode) {
if root != nil {
inorderTraversal(root.Left)
fmt.Println(root.Val)
inorderTraversal(root.Right)
}
}
inorderTraversal(root) // 输出 1 2 3 4 5
需要注意的是,在二叉搜索树中,左子树的所有节点都比根节点小,右子树的所有节点都比根节点大。
7. 图
图是一种复杂的数据结构,它由节点和边组成,每个节点包含一个值和一组邻接节点。在Go中可以使用邻接矩阵或邻接表来实现图。
// 使用邻接表实现图
type Graph struct {
V int // 顶点数
E int // 边数
adj [][]int // 邻接表
marked []bool // 用于dfs的标记
}
// 添加一条边
func (g *Graph) AddEdge(v int, w int) {
g.adj[v] = append(g.adj[v], w)
g.adj[w] = append(g.adj[w], v)
g.E++
}
// 深度优先搜索
func (g *Graph) DFS(v int) {
g.marked[v] = true
fmt.Println(v)
for _, w := range g.adj[v] {
if !g.marked[w] {
g.DFS(w)
}
}
}
// 广度优先搜索
func (g *Graph) BFS(v int) {
var queue []int
queue = append(queue, v)
g.marked[v] = true
for len(queue) != 0 {
v = queue[0]
queue = queue[1:]
fmt.Println(v)
for _, w := range g.adj[v] {
if !g.marked[w] {
queue = append(queue, w)
g.marked[w] = true
}
}
}
}
// 构造一个图
g := new(Graph)
g.V = 5
g.adj = make([][]int, g.V)
g.marked = make([]bool, g.V)
g.AddEdge(0, 1)
g.AddEdge(0, 2)
g.AddEdge(1, 3)
g.AddEdge(1, 4)
// 深度优先遍历
fmt.Println("DFS:")
g.DFS(0)
// 广度优先遍历
fmt.Println("BFS:")
g.BFS(0)
需要注意的是,使用邻接表实现图需要用一个二维数组来保存每个节点的邻接节点。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:使用go实现常见的数据结构 - Python技术站