Go的数据结构与实现【Stack】

介绍

栈是存放值的一种特殊容器,在插入与删除值时,这种结构遵循后进先出(Last-in-first-out,LIFO)的原则,也就是说,值可以任意插入栈中,但每次取出的都是此前插入的最后一个值。

实现

栈必须支持以下方法:
在这里插入图片描述
此外,还可以定义如下的方法:
在这里插入图片描述
此外,还应该提供一个类似构造器的NewStack()方法,当我们开始使用它时,它会初始化一个栈。

基于数组的简单实现

为了实现栈接口,我们可以用一个数组来存放其中的元素。

type T inttype Stack struct {sync.RWMutexarray []T
}

构造器NewStack()方法如下:

func NewStack() *Stack {stack := &Stack{}stack.array = []T{}return stack
}

接下来,我们去实现之前提到的操作方法:

// Push adds t to the top of the stack
func (s *Stack) Push(t T) {s.Lock()s.array = append(s.array, t)s.Unlock()
}

对于Push()方法,只需要将值添加到数组中,Go的原生语法为我们解决了这一步骤。

// Pop removes the top element from the stack
func (s *Stack) Pop() (*T, error) {if s.IsEmpty() {return nil, fmt.Errorf("stack must not be empty")}s.Lock()item := s.array[len(s.array)-1]s.array = s.array[0 : len(s.array)-1]s.Unlock()return &item, nil
}

Pop()方法中,首先检查栈是否为空,如果栈空,则返回空值以及错误信息,否则,将数组第一位取出,整个数组右移一位。

// Size returns the size of the stack
func (s *Stack) Size() int {s.RLock()defer s.RUnlock()return len(s.array)
}func (s *Stack) IsEmpty() bool {s.RLock()defer s.RUnlock()return len(s.array) == 0
}

至于额外的两个方法,即检查栈结构体中成员变量即可。注意到,栈结构体在定义时加入了锁资源,因此以上所有方法都是并发安全的。

单元测试

我们对实现的方法进行单元测试:

package stackimport "testing"var (t1 T = 1t2 T = 2t3 T = 3
)func TestStack_Push(t *testing.T) {stack := NewStack()stack.Push(t1)stack.Push(t2)stack.Push(t3)first := stack.array[0]last := stack.array[len(stack.array)-1]if first != t1 || last != t3 {t.Errorf("wrong order, expected first 1 and last 3 but got %d and %d", t1, t3)}
}func TestStack_Pop(t *testing.T) {stack := NewStack()stack.Push(t1)stack.Push(t2)stack.Push(t3)_, _ = stack.Pop()if size := stack.Size(); size != 2 {t.Errorf("wrong count, expected 2 and got %d", size)}_, _ = stack.Pop()_, _ = stack.Pop()if size := stack.Size(); size != 0 {t.Errorf("wrong count, expected 0 and got %d", size)}_, err := stack.Pop()if err == nil {t.Errorf("stack must not be empty")}
}func TestStack_Size(t *testing.T) {stack := NewStack()stack.Push(t1)stack.Push(t2)stack.Push(t3)if size := stack.Size(); size != 3 {t.Errorf("wrong count, expected 3 and got %d", size)}
}func TestStack_IsEmpty(t *testing.T) {stack := NewStack()empty := stack.IsEmpty()if !empty {t.Errorf("wrong status, expected true and got %t", empty)}stack.Push(t1)empty = stack.IsEmpty()if empty {t.Errorf("wrong status, expected false and got %t", empty)}
}

至此,单元测试通过,我们就完成了栈数据结构的实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/778804.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux:详解TCP协议段格式

文章目录 认识TCPTCP协议段格式 本篇主要总结的是TCP协议的一些字段 认识TCP TCP协议全称是传输控制协议,也就是说是要对于数据的传输进行一个控制 以上所示的是对于TCP协议进行数据传输的一个理解过程 全双工 至此就可以对于TCP协议是全双工的来进行理解了&…

纸上得来终觉浅->代码详解锁升级

背景 最近再看关于锁升级的内容,一方面这个是编写代码时程序性能提高的一个利器,另一方面这部分也会是面试时候的热门话题。那么作者最开始也是通过b站视频包括一些csdn上面的资料去看,最终发现只是有一些结论,而没有具体的例子。…

为何视频订阅者倾向于长期关注:深度探讨用户粘性现象

在当今的数字化时代,视频平台已经成为人们获取信息、娱乐休闲的重要渠道。观察发现,许多用户一旦对某个视频创作者进行关注,往往较少出现主动取关的现象。这一现象背后隐藏着用户行为习惯、内容价值认知以及社区归属感等多种因素的影响&#…

​python学习之变量类型​

print单纯输中的十种数据类型只需要用print()函数即可,()里面直接写变量名。 下面重点介绍print格式输出: 第一种方法:一个萝卜一个坑,下面的代码中,{0}、{1}、{2}分别表示j,i,j*i,单引号里面是输出格式。…

【Webflux】实现全局返回Long转String

基于spring webflux框架,而非springmvc @Configuration public class LongToStringConfig {@Beanpublic ObjectMapper objectMapper() {ObjectMapper objectMapper = new ObjectMapper();SimpleModule simpleModule = new SimpleModule();simpleModule.addSerializer(Long.cla…

什么是土壤墒情检测站?它在农业生产中有什么作用?

土壤墒情检测站是一种专门用于监测土壤水分状况和土壤水力性质的设备。它由多个传感器和数据采集单元组成,能够实时监测土壤中的水分含量、土壤温度等参数,并收集和记录相关的数据,提供土壤墒情(即土壤水分状态)的详细…

Python教程:一文掌握Python多线程(很详细)

目录 1.什么是多线程? 1.1多线程与单线程的区别 1.2 Python 中的多线程实现方式 2.使用 threading 模块创建和管理线程 2.1创建线程:Thread 类的基本用法 2.2线程的启动和执行:start() 方法 2.3线程的同步和阻塞:join() 方…

2024年华为OD机试真题-图像物体的边界-Java-OD统一考试(C卷)

题目描述: 给定一个二维数组M行N列,二维数组里的数字代表图片的像素,为了简化问题,仅包含像素1和5两种像素,每种像素代表一个物体,2个物体相邻的格子为边界,求像素1代表的物体的边界个数。 像素1代表的物体的边界指与像素5相邻的像素1的格子,边界相邻的属于同一个边界,…

docker 安装Sentinel

1.拉取镜像:docker pull bladex/sentinel-dashboard 2.运行镜像:docker run --name sentinel -d -p 8858:8858 -d bladex/sentinel-dashboard 3. 访问地址: 本地地址:http://localhost:8858 (默认端口为8080) 远程地址&#xf…

【学习】软件测试人员如何设计出优秀的测试用例

在软件开发的过程中,测试用例如同工程质量的守护者,它们的存在确保了软件产品的稳定性和可靠性。然而,如何设计出优秀的测试用例,让其在千变万化的软件世界中独领风骚,成为众多测试工程师追寻的目标。本文将为你揭示其…

Android RecyclerView 滑动后选中的条目居中显示

话不多说先看效果: 实录效果视频如下 滚动居中 RecyclerView 在原有的RecyclerView 基础上操作,其他步骤不变,只是替换一下 manager 步骤 导入依赖 maven { url https://www.jitpack.io }//无限滚动implementation com.github.ZhaoChanghu:GalleryLayou…

(Java学习)File类与IO流

File类与IO流 文章目录 File类与IO流1. File类1.1 File类理解1.2 构造器1.3 常用方法1.4 练习 2. IO流概述2.1 IO流理解2.2 流的分类2.3 基础IO流的框架 3. FileReader/FileWriter3.1 执行步骤3.2 注意 4. FileInputStream / FileOutputStream5. 缓冲流6. 转换流的使用7. 对象流…

1、Cocos Creator 基础入门

目录 Cocos Creator 是什么? 语言支持 功能特性 工作流程 功能模块 相关游戏 参考 Cocos Creator 是什么? Cocos Creator 既是一款高效、轻量、免费开源的跨平台 2D&3D 图形引擎,也是一个实时 2D&3D 数字内容创作平台。拥有…

本地GDB 在geoserver发布地图服务

文章目录 简要说明maven依赖样例代码 简要说明 geoserver本身是不支持GDB的发布&#xff0c;不过可以利用gdal&#xff0c;将GDB的图层转为shpfile&#xff0c;就可以进行发布。maven依赖 <!--geoserver需要的jar--><dependency><groupId>com.github.dov-vl…

Java开发过程中如何进行进制换换

最近由于工作上的需要&#xff0c;遇到进制转换的问题。涉及到的进制主要是十进制、十六进制、二进制转换。 1、十进制转十六进制、二进制 调用java自带的api,测试十进制转16进制、2进制 package com.kangning.common.utils.reflect;/*** 十进制 转 十六进制* 十进制 转 二进…

AcWing第147场周赛(5556.牛的语言学)

牛语单词通过以下规则构造&#xff1a; 牛语单词仅由小写字母构成。牛语单词的具体结构为&#xff1a;词根若干个&#xff08;0 个或更多&#xff09;后缀&#xff0c;其中&#xff1a; 词根为长度大于 4 的字符串。后缀为长度 2 或 3 的字符串。在构成单词时&#xff0c;不允…

机器学习算法的另一个分支-贝叶斯算法原理(贝叶斯要解决什么问题)

目录 一、贝叶斯简介 二、贝叶斯要解决的问题 三、例子&#xff08;公式推导&#xff09; 四、实例 1. 拼写纠正实例 2. 垃圾邮件过滤实例 一、贝叶斯简介 1. 贝叶斯&#xff1a;英国数学家。1702年出生于伦敦&#xff0c;做过神甫。贝叶斯在数学方面主要研究概率论.对于…

Golang基础-3

Go语言基础 介绍 基础 1. 条件语句 2. 选择语句 3. 循环语句 4. goto关键字 介绍 本文介绍Go语言中条件语句、选择语句、循环语句、break、continue、goto关键字等相关知识。 基础 1. 条件语句 实现程序逻辑时&#xff0c;需要通过不同的判断条件去执行相应的语句。…

初识C++ · 入门(1)

目录 前言&#xff1a; 1 命名空间 2 输入和输出 3 缺省参数 5 函数重载 前言&#xff1a; C与C语言是有一定交集的&#xff0c;可以理解为本贾尼在使用C语言的时候认为有缺陷&#xff0c;于是加了一些小语法进行改良&#xff0c;后来经过委员会的修改&#xff0c;C98问世…

深度学习故障诊断实战 | 数据预处理之基于滑动窗的数据样本增强

前言 本期给大家分享介绍如何基于滑动窗方法进行数据样本增强 背景 深度学习模型训练需要大量的样本。在故障诊断领域&#xff0c;每个类别大都会达到300个样本。但是在实际公开数据集中&#xff0c;以CWRU数据集为例&#xff0c;每个类别只有24组数据&#xff0c;这明显是不…