@

一 前言

go语言中,并没有栈与队列相关的数据结构,但是我们可以借助切片来实现栈与队列的操作;接下来我们一起实现栈与队列基本操作,并且还会实现用栈实现队列用队列实现栈的操作。

二 实现栈与队列基本操作

2.1 栈基本操作

go语言实现栈和队列主要用到append 和切片(用内置数组类型进行操作)

//创建栈
stack := make([]int, 0)
//push压入栈
stack = append(stack, 10)
//pop弹出
v := stack[len(stack)-1]
stack = stack[:len(stack)-1]
//检查栈空
len(stack) == 0

2.2 队列基本操作

//创建队列
queue := make([]int, 0)
//enqueue入队
queue = append(queue, 10)
//dequeue出队
v := queue[0]
queue = queue[1:]
//检查队列为空
len(queue) == 0

三 用栈实现队列

3.1 理论

使用栈来模式队列的行为,如果仅仅用一个栈,是一定不行的,所以需要两个栈一个输入栈,一个输出栈,这里要注意输入栈和输出栈的关系。

下面动画模拟以下队列的执行过程如下:

执行语句:

queue.push(1);
queue.push(2);
queue.pop(); 注意此时的输出栈的操作
queue.push(3);
queue.push(4);
queue.pop();
queue.pop();注意此时的输出栈的操作
queue.pop();
queue.empty();



在push数据的时候,只要数据放进输入栈就好,但在pop的时候,操作就复杂一些,输出栈如果为空,就把进栈数据全部导入进来(注意是全部导入),再从出栈弹出数据,如果输出栈不为空,则直接从出栈弹出数据就可以了。

最后如何判断队列为空呢?如果进栈和出栈都为空的话,说明模拟的队列为空了。

3.2 算法题

接下来看一下LeetCode原题

232. 用栈实现队列

请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):

实现 MyQueue 类:

void push(int x) 将元素 x 推到队列的末尾

int pop() 从队列的开头移除并返回元素

int peek() 返回队列开头的元素

boolean empty() 如果队列为空,返回 true ;否则,返回 false

说明:

你 只能 使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。

你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。

3.3 思路

解决这个问题,需要一个输出栈和输入栈

先将数据放到输入栈,再把数据从输入栈放到输出栈,此时输出栈输出数据的顺序就和队列一样了,先入先出

3.4 代码部分

type MyQueue struct {
stackIn []int // 用来保存Push数据
stackOut []int // 用来保存Pop数据
} // 栈构造器
func Constructor() MyQueue {
return MyQueue{
stackIn: make([]int, 0),
stackOut: make([]int, 0),
}
} func (this *MyQueue) Push(x int) {
// 判断stackOut中是否有元素,有的话全部放到stackIn
for len(this.stackOut) != 0 {
val := this.stackOut[len(this.stackOut)-1]
this.stackOut = this.stackOut[:len(this.stackOut)-1]
this.stackIn = append(this.stackIn, val)
}
// 将数据加进stackIn
this.stackIn = append(this.stackIn, x)
} func (this *MyQueue) Pop() int {
// 判断stackIn中是否有元素,有的话全部放到stackOut
for len(this.stackIn) != 0 {
val := this.stackIn[len(this.stackIn)-1]
this.stackIn = this.stackIn[:len(this.stackIn)-1]
this.stackOut = append(this.stackOut, val)
}
// stackOut为零,说明没有元素,return 0
if len(this.stackOut) == 0 {
return 0
}
// stackOut Pop 元素
res := this.stackOut[len(this.stackOut)-1]
this.stackOut = this.stackOut[:len(this.stackOut)-1]
return res
} func (this *MyQueue) Peek() int {
// 调用Pop()方法
val := this.Pop()
// val为零,说明没有元素,return 0
if val == 0 {
return 0
}
// Pop()方法删除了val,这里加上
this.stackOut = append(this.stackOut, val)
return val
} func (this *MyQueue) Empty() bool {
// 两个栈都为空,说明为空,否则不为空
return len(this.stackOut) == 0 && len(this.stackIn) == 0
}

代码可以直接拿到力扣上运行。我已经将细节全部用注释解释了,如果不懂可以私信博主。

四 用队列实现栈

4.1 理论

队列模拟栈,其实一个队列就够了,那么我们先说一说两个队列来实现栈的思路。

队列是先进先出的规则,把一个队列中的数据导入另一个队列中,数据的顺序并没有变,并没有变成先进后出的顺序。

所以用栈实现队列, 和用队列实现栈的思路还是不一样的,这取决于这两个数据结构的性质。

但是依然还是要用两个队列来模拟栈,只不过没有输入和输出的关系,而是另一个队列完全用又来备份的!

如下面动画所示,用两个队列que1和que2实现队列的功能,que2其实完全就是一个备份的作用,把que1最后面的元素以外的元素都备份到que2,然后弹出最后面的元素,再把其他元素从que2导回que1。

模拟的队列执行语句如下:

queue.push(1);
queue.push(2);
queue.pop(); // 注意弹出的操作
queue.push(3);
queue.push(4);
queue.pop(); // 注意弹出的操作
queue.pop();
queue.pop();
queue.empty();

4.2 算法题

接下来看一下LeetCode原题

225. 用队列实现栈

请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。

实现 MyStack 类:

void push(int x) 将元素 x 压入栈顶。

int pop() 移除并返回栈顶元素。

int top() 返回栈顶元素。

boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。

注意:

你只能使用队列的基本操作 —— 也就是 push to back、peek/pop from front、size 和 is empty 这些操作。

你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。

4.3 思路

用两个队列que1和que2实现队列的功能,que2其实完全就是一个备份的作用,把que1最后面的元素以外的元素都备份到que2,然后弹出最后面的元素,再把其他元素从que2导回que1。

4.4 使用两个队列实现

type MyStack struct {
//创建两个队列
queue1 []int
queue2 []int
} func Constructor() MyStack {
return MyStack{ //初始化
queue1:make([]int,0),
queue2:make([]int,0),
}
} func (this *MyStack) Push(x int) {
//先将数据存在queue2中
this.queue2 = append(this.queue2,x)
//将queue1中所有元素移到queue2中,再将两个队列进行交换
this.Move()
} func (this *MyStack) Move(){
if len(this.queue1) == 0{
//交换,queue1置为queue2,queue2置为空
this.queue1,this.queue2 = this.queue2,this.queue1
}else{
//queue1元素从头开始一个一个追加到queue2中
this.queue2 = append(this.queue2,this.queue1[0])
this.queue1 = this.queue1[1:] //去除第一个元素
this.Move() //重复
}
} func (this *MyStack) Pop() int {
val := this.queue1[0]
this.queue1 = this.queue1[1:] //去除第一个元素
return val } func (this *MyStack) Top() int {
return this.queue1[0] //直接返回
} func (this *MyStack) Empty() bool {
return len(this.queue1) == 0
}

4.5 优化

其实这道题目就是用一个队列就够了。

一个队列在模拟栈弹出元素的时候只要将队列头部的元素(除了最后一个元素外) 重新添加到队列尾部,此时在去弹出元素就是栈的顺序了。

4.6 使用一个队列实现

type MyStack struct {
queue []int//创建一个队列
} /** Initialize your data structure here. */
func Constructor() MyStack {
return MyStack{ //初始化
queue:make([]int,0),
}
} /** Push element x onto stack. */
func (this *MyStack) Push(x int) {
//添加元素
this.queue=append(this.queue,x)
} /** Removes the element on top of the stack and returns that element. */
func (this *MyStack) Pop() int {
n:=len(this.queue)-1//判断长度
for n!=0{ //除了最后一个,其余的都重新添加到队列里
val:=this.queue[0]
this.queue=this.queue[1:]
this.queue=append(this.queue,val)
n--
}
//弹出元素
val:=this.queue[0]
this.queue=this.queue[1:]
return val } /** Get the top element. */
func (this *MyStack) Top() int {
//利用Pop函数,弹出来的元素重新添加
val:=this.Pop()
this.queue=append(this.queue,val)
return val
} /** Returns whether the stack is empty. */
func (this *MyStack) Empty() bool {
return len(this.queue)==0
}

Go实现栈与队列基本操作的更多相关文章

  1. 栈与队列基本操作 Java实现

    一.顺序栈 //数组实现顺序栈 public class OrderStack { private String[] elem; private int top; OrderStack(int k) ...

  2. c++用类写栈和队列的简单基本操作(实验)

    继续更文.这次用类来写栈和队列,都是用数组模拟的: 以下是栈和队列的定义: 然后分别是栈和队列的类: 完整代码贴上: 栈 //使用类来定义栈 class ZHAN { public: STACK s; ...

  3. 二、 编写一个类,用两个栈实现队列,支持队列的基本操作(add,poll,peek)

    请指教交流! package com.it.hxs.c01; import java.util.Stack; /* 编写一个类,用两个栈实现队列,支持队列的基本操作(add,poll,peek) */ ...

  4. SDUT-3335_数据结构实验之栈与队列八:栈的基本操作

    数据结构实验之栈与队列八:栈的基本操作 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 堆栈是一种基本的数据结构.堆栈具 ...

  5. C实现栈和队列

    这两天再学习了数据结构的栈和队列,思想很简单,可能是学习PHP那会没有直接使用栈和队列,写的太少,所以用具体代码实现的时候出现了各种错误,感觉还是C语言功底不行.栈和队列不论在面试中还是笔试中都很重要 ...

  6. 用JS描述的数据结构及算法表示——栈和队列(基础版)

    前言:找了上课时数据结构的教程来看,但是用的语言是c++,所以具体实现在网上搜大神的博客来看,我看到的大神们的博客都写得特别好,不止讲了最基本的思想和算法实现,更多的是侧重于实例运用,一边看一边在心里 ...

  7. Swift 算法实战之路:栈和队列

    这期的内容有点剑走偏锋,我们来讨论一下栈和队列.Swift语言中没有内设的栈和队列,很多扩展库中使用Generic Type来实现栈或是队列.笔者觉得最实用的实现方法是使用数组,本期主要内容有: 栈和 ...

  8. 数据结构与算法(C/C++版)【栈与队列】

    第三章<栈与队列> (一)栈简介  栈(Stack):只允许在一端进行插入或删除操作的线性表.首先栈是一种线性表,但是限定这种线性表只能在某一端进行插入和删除操作栈顶(top):线性表允许 ...

  9. 数据结构(C语言版)-第3章 栈和队列

    3.1 栈和队列的定义和特点3.2 案例引入3.3 栈的表示和操作的实现3.4 栈与递归3.5 队列的的表示和操作的实现3.6 案例分析与实现 基本操作有入栈.出栈.读栈顶元素值.建栈.判断栈满.栈空 ...

随机推荐

  1. Spring(二)-生命周期 + 自动装配(xml) +自动装配(注解)

    1.生命周期 **Spring容器的 bean **的生命周期: 1.1 默认生命周期 1.1.1 生命周期 调用构造方法,创建实例对象: set方法,给实例对象赋值: init 初始化方法 初始化对 ...

  2. KingbbaseES V8R6集群维护案例之---集群之间数据迁移

    案例说明: 生产环境是集群环境,测试环境是集群,现需要将生产环境的数据迁移到测试集群中运行,本文档详细介绍了从集群环境迁移数据的操作步骤,可以作为生产环境迁移数据的参考. 适用版本: Kingbase ...

  3. plpgsql 编译执行

    Oracle 的存储过程或函数提供了两种执行方式: 解释执行:将源代码逐条转换成目标代码,解释一条,执行一条的过程.PLPGSQL将语句翻译成中间形式的系统代码,并在运行时进行解释. 编译执行:将源代 ...

  4. Linux使用密钥登录SSH

    输入命令和上传密钥时需要注意当前目录.账号和读写权限 生成密钥 使用服务器生成(方法一,推荐) 1.1生成密钥 #ssh-keygen(这里pwd为当前账号的home目录) 1.2下载密钥 .id_r ...

  5. 小程序 AI/AR 能力

    一.关于 VisionKit 1.定义 VisionKit 为小程序提供了开发 AR 功能的能力,包含了 AR 在内的视觉算法. 2.版本 提供了 V1 和 V2 两个版本,区别如下: V1平面接口, ...

  6. 记一个nginx server_name配置多个时的坑

    文章转载自:https://blog.csdn.net/u011296355/article/details/106740860/ 背景 为了区分线上环境和测试环境,我弄了个自己测试专用的域名test ...

  7. 不停机为虚拟机添加主机磁盘(以VMware Workstation为例)

    VMware Workstation软件上安装的centos7系统,新增磁盘后使用fdisk -l命令查看不到新增的磁盘,有没有办法在不重启的情况下添加上新磁盘? 有办法 具体如下: # 查看主机总线 ...

  8. 20. 使用Fluentd发送告警邮件

    告警是预防系统故障的一个重要工具,目前已经有许多成熟的方案通过监控系统运行指标来进行阈值预警.今天简单了解一下如何使用Fluentd实现邮件告警功能. Fluentd的告警是基于日志分析实现的,通过监 ...

  9. 用户输入学号,如果是以aabcddef开头,并且后边是4位数字,前两位大于06小于等于当前年份。判断用户输入是否合法

    package seven_topic; import java.util.*; public class p_19_1 { public static void main(String[] args ...

  10. 一个好玩的deep learning Demo!

    对于生活中的熟悉的动物,我们人脑经过一次扫描,便可以得到该动物的物种!那么机器是如何识别这个图片上的动物是属于哪一物种呢? 本次实验借生活中最常见的猫和狗来探究其原理! 环境准备: tensorflo ...