使用go实现常见的数据结构

下面我将详细讲解使用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技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • Java数据结构之实现跳表

    Java数据结构之实现跳表,是一篇对跳表数据结构的详细讲解。 背景 跳表是一种基于有序链表的高效查找算法,它的查找时间复杂度为O(logn),相比于普通链表的O(n),具有很大的优势。本文将介绍跳表的实现过程。 实现跳表 1. 跳表结构体 跳表的数据结构体实现包含以下四项: 头结点head:表示链表的起始位置。 节点Node:跳表中的节点,包含表层链表和下层…

    数据结构 2023年5月17日
    00
  • C语言编程简单却重要的数据结构顺序表全面讲解

    C语言编程简单却重要的数据结构顺序表全面讲解 什么是顺序表? 顺序表是一种线性表,指的是一组有限元素的有限序列,其元素的逻辑顺序与它们在分配到的内存地址上的物理顺序相同或者等价。也就是说,顺序表中的元素按照其在内存中的位置依次存放。 顺序表的实现方式 顺序表的实现方式一般是使用数组,数组中的每一个元素对应着顺序表中的一个元素,位置相对应。 顺序表的优点 支持…

    数据结构 2023年5月17日
    00
  • C++数据结构与算法之判断一个链表是否为回文结构的方法

    当我们遇到判断一个链表是否为回文结构的问题时,可以考虑使用如下的方法: 遍历链表,将链表节点的值存储到一个数组或者栈中。 遍历链表,将链表节点的值与前面存储的值进行比较,如果全部相同,则证明链表为回文结构。 下面是详细的代码实现和示例说明: 实现 首先,我们需要定义一个链表节点的结构体,包括节点值和指向下一个节点的指针: struct ListNode { …

    数据结构 2023年5月17日
    00
  • Java数据结构之实现哈希表的分离链接法

    Java数据结构之实现哈希表的分离链接法 哈希表是一种非常常用的数据结构,它将数据存储在一个数组中,每个数组元素都存储着链表中的一个节点,这样可以实现高效的数据存储和查找操作。在哈希表中,我们可以通过哈希函数将关键字映射到数组中的特定位置。 但是,当哈希表的负载因子过高时,就会造成哈希冲突,这意味着两个或更多的关键字映射到了同一个数组位置。一种常见的解决方案…

    数据结构 2023年5月17日
    00
  • 用C语言举例讲解数据结构中的算法复杂度结与顺序表

    让我来为你讲解“用C语言举例讲解数据结构中的算法复杂度结与顺序表”的完整攻略。具体如下: 一、算法复杂度 1.1 什么是算法复杂度 算法复杂度是衡量算法运行效率的重要指标。包括时间复杂度和空间复杂度。时间复杂度指算法解决问题所用的时间,通常用大O符号表示;空间复杂度指算法解决问题所需的内存空间大小。 1.2 如何分析算法复杂度 可以从以下三个方面来分析算法复…

    数据结构 2023年5月17日
    00
  • 环形队列的实现 [详解在代码中]

    1 package DataStructures.Queue.Array.Exerice; 2 3 /** 4 * @author Loe. 5 * @project DataStructures&Algorithms 6 * @date 2023/5/8 7 * @ClassInfo 环形队列 8 * 主要使用取模的特性来实现环形特征 9 */ 1…

    算法与数据结构 2023年5月8日
    00
  • 一文带你走进js数据类型与数据结构的世界

    一文带你走进JS数据类型与数据结构的世界 一、JS数据类型 1. 原始类型 JS中原始类型包括:Undefined、Null、Boolean、Number、String、Symbol(ES6新增)。 其中Undefined和Null分别代表未定义和空值,Boolean表示布尔值,Number表示数字,String表示字符串,Symbol是ES6新增的一种基础…

    数据结构 2023年5月17日
    00
  • Java数据结构之常见排序算法(上)

    Java数据结构之常见排序算法(上) 本篇文章将介绍常见的排序算法,包括冒泡排序、选择排序、插入排序、快速排序和归并排序。这些排序算法既是学习算法和数据结构的入门知识,也是在实际工作中常用的基础算法。 冒泡排序 冒泡排序是一种简单的排序算法,它的基本思想是从前往后依次比较相邻的两个元素,如果前面的元素比后面的元素大,则交换它们的位置,重复这个过程,每一轮比较…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部