@

一 前言

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. 实时降噪(Real-time Denoising):Spatio-Temporal Filtering

    目录 空间滤波(Spatial Filtering) 基于距离的高斯滤波 双边滤波(Bilateral filtering) 联合双边滤波(Joint Bilateral filtering)[201 ...

  2. python 二分法查找字典中指定项第一次出现的索引

    import time #引入time库,后续计算时间. inform_m = {} #创建母字典 inform_s = {} #母字典下嵌套的子字典 #给母字典添加键-值 for i in rang ...

  3. KingbaseES V8R6集群外部备份案例

    案例说明: 本案例采用sys_backup.sh执行物理备份,备份使用如下逻辑架构:集群采用CentOS 7系统,repo采用kylin V10 Server. 一主一备+外部备份 此场景为主备双机常 ...

  4. Macos下用pycharm运行django项目死活安装不上mysqlclient怎么办!!??

    花了我三天时间,佛了 我刚从win过渡到mac,想着把代码迁移一下. 然后看到依赖里面有一个mysqlclient,然后pip3 install死活装不上 解决方案: 在这里写上这个 然后就好,死了

  5. 使用 MAUI 在 Windows 和 Linux 上绘制 PPT 的图表

    我在做一个图表工具软件,这个软件使用 MAUI 开发.我的需求是图表的内容需要和 PPT 的图表对接,需要用到 OpenXML 解析 PPT 内容,读取到 PPT 图表元素的内容,接着使用 MAUI ...

  6. windows清理必看

    清理缓存 代码如下 介绍此文件夹都是缓存文件全选删除即可 ctrl+A全选shift+del强制删除(不会添加到回收站) %temp% 找到C盘右击属性选择想要删除的文件进行清理即可 清理完点击清理系 ...

  7. Redis变慢?深入浅出Redis性能诊断系列文章(一)

    (本文首发于"数据库架构师"公号,订阅"数据库架构师"公号,一起学习数据库技术)   Redis 作为一款业内使用率最高的内存数据库,其拥有非常高的性能,单节点 ...

  8. 跨语言调用C#代码的新方式-DllExport

    简介 上一篇文章使用C#编写一个.NET分析器文章发布以后,很多小伙伴都对最新的NativeAOT函数导出比较感兴趣,今天故写一篇短文来介绍一下如何使用它. 在以前,如果有其他语言需要调用C#编写的库 ...

  9. Solutions:Elastic SIEM - 适用于家庭和企业的安全防护 ( 一)

  10. C++ 中std::的使用

    std是一个类(输入输出标准),它包括了cin成员和cout成员,using name space std ;以后才能使用它的成员.#include<iostream.h>中不存在类std ...