栈和队列

栈和队列——python 一、栈 定义一个栈 栈的应用——括号匹配问题 栈的应用——迷宫问题 二、队列 自定义队列 python队列的内置模块 队列应用——打印文件后五行 队列应用——迷宫问题 python的数据结构与算法之栈与队列 阅读详情

栈和队列

栈和队列都是动态集合,在其上进行DELETE操作所移除的元素都是预先设定的。在栈中,被删除的元素是最近插入的元素:栈实现的是一种后进先出(LIFO)策略;队列中被删除的总是集合中存在时间最长的元素:队列实现的是先进先出(FIFO)策略

栈

栈上的INSERT操作被称为压入(push),无参数的DELETE操作称为弹出(pop)。可以使用一个数组S[1…n]来实现一个最多可容纳n个元素的栈,该数组有一个属性S.top,指向最新插入的元素,栈中包含的元素为S[1…S.top],其中S[1]是栈底元素,S[S.top]是栈顶元素

当S.top=0时,栈中不包含任何元素,栈为空,要测试一个栈是否为空可以用查询操作STACK-EMPTY,如果对一个空栈执行弹出操作,则称栈下溢,如果S.top超过top,则称为上溢

STACK-EMPTY(S)
1   if S.top == 0
2       return TRUE
3   else return FALSE

PUSH(S, x)
1   S.top = S.top + 1
2   S[S.top] = x

POP(S)
1   if STACK-EMPTY(S)
2       error "underflow"
3   else S.top = S.top -1
4       return S[S.top + 1]

Java Stack源码实现

Stack继承Vector类并提供初始化、入栈、出栈、判空、搜索等一系列操作

入栈

push(E item)入栈操作调用父类Vector的addElement(E obj)方法,该方法上添加synchronized关键字,是线程安全的。addElement方法内部会首先
将modCount加1,然后调用ensureCapacityHelper判断是否需要扩容,如果需要扩容将调用grow(int minCapacity)进行扩容,在扩容方法中会判断是否设置capacityIncrement,如果设置此属性将此属性设置值进行扩容操作,如果未设置则将容量扩充一倍,并将数据复制到扩容之后的数组。ensureCapacityHelper方法执行结束后,下一步将需要推入数据放到elementCount++位置,elementCount为未入栈前栈中已有元素数量

// 入栈方法
public E push(E item) {
    addElement(item);

    return item;
}

// Vector添加元素方法,线程安全
public synchronized void addElement(E obj) {
    modCount++;
    ensureCapacityHelper(elementCount + 1);
    elementData[elementCount++] = obj;
}

// 判断是否需要扩容
private void ensureCapacityHelper(int minCapacity) {
    // overflow-conscious code
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

// 扩容方法
private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                     capacityIncrement : oldCapacity);
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    elementData = Arrays.copyOf(elementData, newCapacity);
}
出栈

pop()出栈操作将栈顶元素取出并移除,线程安全

// 取出栈顶元素并移除
public synchronized E pop() {
    E       obj;
    int     len = size();

    obj = peek();
    removeElementAt(len - 1);

    return obj;
}

// 取出栈顶元素
public synchronized E peek() {
    int     len = size();

    if (len == 0)
        throw new EmptyStackException();
    return elementAt(len - 1);
}

// 移除栈顶元素
public synchronized void removeElementAt(int index) {
    modCount++;
    if (index >= elementCount) {
        throw new ArrayIndexOutOfBoundsException(index + " >= " +
                                                 elementCount);
    }
    else if (index < 0) {
        throw new ArrayIndexOutOfBoundsException(index);
    }
    int j = elementCount - index - 1;
    if (j > 0) {
        System.arraycopy(elementData, index + 1, elementData, index, j);
    }
    elementCount--;
    elementData[elementCount] = null; /* to let gc do its work */
}
检查是否为空栈

empty()操作检查栈中是否还有元素

public boolean empty() {
    return size() == 0;
}

队列

队列上的INSERT操作称为入队,DELETE操作称为出队,队列遵循先进先出的策略。队列有队头和队尾,当一个元素入队时,被放在队尾的位置,当出队时则从队头

可以利用数组Q[1…n]来实现一个最多容纳n-1个元素的队列。该队列有一个属性Q.head指向队头元素,属性Q.tail则指向下一个新元素将要插入队位置,队列中的元素存放在位置Q.head,Q.head + 1, … , Q.tail - 1,并在最后的位置"环绕",当Q.head = Q.tail时,队列为空,初始Q.head=Q.tail=1。如果试图从空队列删除一个元素,队列将发生下溢。当Q.head=Q.tail + 1,队列满,此时尝试插入元素将发生上溢

ENQUEUE(Q,x)
1   Q[Q.tail] = x
2   if Q.tail == Q.length
3       Q.tail = 1
4   else Q.tail = Q.tail + 1

DEQUEUE(Q)
1   x = Q[Q.head]
2   if Q.head == Q.length
3       Q.head = 1
4   else Q.head = Q.head + 1
5   return x

Java ArrayBlockingQueue实现

JDK本身实现的队列有很多种,这里我们看一下ArrayBlockingQueue的源码实现
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cohWYSOw-1619080467268)(./image/jdk queue实现.png)]

初始化ArrayBlockingQueue

ArrayBlockingQueue提供三个构造函数进行初始化,三个函数都需要传入capacity参数,指定指定阻塞队列的固定容量大小。在构造函数中会初始化一个指定capacity容量的Object数组,并且初始化ReentrantLock可重入锁,用户可以指定是否是公平锁,默认是非公平锁。初始化锁之后会初始化线程协作条件notEmpty、notFull

入队操作

入队方法一共有三个,分别提供非阻塞入队、阻塞入队、阻塞超时入队,这三个暴露给用户的入队方法,都会调用私有方法enqueue(E x),此方法实现真正的入队操作,并且在结束时会执行notEmpty.signal(),实现唤醒阻塞出队操作。无论是阻塞入队,还是非阻塞入队都被加上了可重入锁

// 非阻塞入队,当队列没有空余空间时返回false
public boolean offer(E e) {
    checkNotNull(e);
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        if (count == items.length)
            return false;
        else {
            enqueue(e);
            return true;
        }
    } finally {
        lock.unlock();
    }
}

// 阻塞入队,当没有多余空间可以添加新的元素时,将阻塞入队操作,直到被唤醒
public void put(E e) throws InterruptedException {
    checkNotNull(e);
    final ReentrantLock lock = this.lock;
    lock.lockInterruptibly();
    try {
        while (count == items.length)
            notFull.await();
        enqueue(e);
    } finally {
        lock.unlock();
    }
}

// 阻塞超时入队,可以设置阻塞时间,若没有多余空间提供入队将进入阻塞状态,当到达超时时间还未被唤醒将返回false
public boolean offer(E e, long timeout, TimeUnit unit)
    throws InterruptedException {

    checkNotNull(e);
    long nanos = unit.toNanos(timeout);
    final ReentrantLock lock = this.lock;
    lock.lockInterruptibly();
    try {
        while (count == items.length) {
            if (nanos <= 0)
                return false;
            nanos = notFull.awaitNanos(nanos);
        }
        enqueue(e);
        return true;
    } finally {
        lock.unlock();
    }
}

// 真正实现入队操作的方法,入队完成后唤醒出队操作
private void enqueue(E x) {
    // assert lock.getHoldCount() == 1;
    // assert items[putIndex] == null;
    final Object[] items = this.items;
    items[putIndex] = x;
    if (++putIndex == items.length)
        putIndex = 0;
    count++;
    notEmpty.signal();
}
出队操作

暴露给用户的出队方法同样支持三种方式,分别提供非阻塞出队、阻塞出队、阻塞超时出队,最终都会调用私有方法dequeue(),实现真正的出队操作,出队成功后会唤醒入队阻塞操作,三种方式的出队操作同样也被加上了可重入锁

// 非阻塞出队
public E poll() {
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        return (count == 0) ? null : dequeue();
    } finally {
        lock.unlock();
    }
}

// 阻塞出队,当队列中没有元素时便会阻塞出队操作
public E take() throws InterruptedException {
    final ReentrantLock lock = this.lock;
    lock.lockInterruptibly();
    try {
        while (count == 0)
            notEmpty.await();
        return dequeue();
    } finally {
        lock.unlock();
    }
}

// 阻塞超时出队,当队列中没有元素,则会进入阻塞,当阻塞时间达到设定时间还未被唤醒则会返回null
public E poll(long timeout, TimeUnit unit) throws InterruptedException {
    long nanos = unit.toNanos(timeout);
    final ReentrantLock lock = this.lock;
    lock.lockInterruptibly();
    try {
        while (count == 0) {
            if (nanos <= 0)
                return null;
            nanos = notEmpty.awaitNanos(nanos);
        }
        return dequeue();
    } finally {
        lock.unlock();
    }
}

// 真正的出队操作,出队完成后,如果迭代器不为空更新迭代器中元素,唤醒入队操作
private E dequeue() {
    // assert lock.getHoldCount() == 1;
    // assert items[takeIndex] != null;
    final Object[] items = this.items;
    @SuppressWarnings("unchecked")
    E x = (E) items[takeIndex];
    items[takeIndex] = null;
    if (++takeIndex == items.length)
        takeIndex = 0;
    count--;
    if (itrs != null)
        itrs.elementDequeued();
    notFull.signal();
    return x;
}

结语

栈和队列都是使用比较多的数据结构,如果在Java中需要用到不妨看一看JDK的实现

栈和队列算法总结 二、栈和队列          目录:        1.设计含min函数的栈,要求min、push和pop的时间复杂度都是o(1)。        2.设计含min函数的栈的另解        3.用两个栈实现队列        4.用两个队列实现栈          5.栈的push、pop序列是否一致        6.递归反转一个栈,要求不得重新申请一个同样的栈,空间复杂 阅读详情

相关推荐

Unity安卓打包实战:SDK与JDK配置全攻略

本文详细介绍了Unity安卓打包过程中SDK与JDK的配置方法,包括工具下载、安装步骤、环境变量设置及常见错误排查。通过实战指南帮助开发者快速完成Unity安卓打包环境搭建,提升开发效率。

weixin_30338481的博客 420

C语言 环形队列

队列 :队列是一种先进先出的数据结构。比如说 排队买票,有一个售票口,最多能排30人,那么最大存储空间就是30人,每当有1个新人过来排队,就会站在队尾,这就叫入队,每当有1个人买到票了,就会离开,就叫出队。生活中,最前面1个人买完票后,队伍中剩下的每1个人都会向前走1位,对于计算机来说,每个人动一下意味着要执行更多的代码,如果卖票的人卖完第1个 ,第一个人就离开,售票员就走向第2个,再走向第3个,直

github_35041937的博客 9698

figma MCP + cursor如何将设计稿生成前端页面

Figma MCP配置与代码生成指南 本文详细介绍了如何在Cursor中配置Figma MCP(多上下文处理器)的完整流程:从获取Figma API密钥、设置MCP服务器配置,到添加代码生成规则。关键步骤包括生成Figm a个人访问令牌、配置cursor settings文件、启用MCP服务,以及设置代码规则(包含TypeScript/Vue技术栈规范、BEM命名规则等)。最后提供了将Figma设计稿转化为Vue页面的prompt模板,涵盖文件结构、图片处理、样式规范等具体要求,确保生成代码与设计稿高度一致

weixin_45644355的博客 2912

【栈和队列】C语言简单应用 ⌊栈和队列互相实现,循环队列⌉

栈和队列简单应用

qq_62852431的博客 2299

别再只跑memtester了!嵌入式Linux内存压力测试,这5个参数和场景你试过吗?

本文深入探讨了嵌入式Linux内存压力测试的高级技巧,重点解析了memtester工具的5个关键参数和实战场景。通过物理地址测试、迭代控制、内存分配策略等调优方法,帮助开发者有效检测内存稳定性问题,适用于长期运行设备、特定故障重现等复杂场景,提升嵌入式系统可靠性。

weixin_30838873的博客 425

GNSS - PPP软件 - GAMP 在VS2019/2022下完成调试、跑通程序(超详细!)

WIN32;_DEBUG;_CONSOLE;O_WARNINGS;ENAGLO;ENACMP;ENAGAL;ENAQZS;NFREQ=3。

qq_43381998的博客 8251

C# 栈和队列

/求栈的长度//判断栈是否为空//清空操作//入栈操作T Pop();//出栈操作T Peek();//取栈顶元素}//取得队列长度的属性//求队列的长度//判断对列是否为空//清空队列//入队//出队T Peek();//取队头元素。

钢铁男儿 1360

AI之KE:Knowledge Engineering知识工程的简介、发展、应用案例之详细攻略

AI之KE:Knowledge Engineering知识工程的简介、发展、应用案例之详细攻略 目录 Knowledge Engineering知识工程的简介 0.1、What 0.2、How 0.3、Why 1、知识工程过程的5个活动 2、知识图谱的应用 Knowledge Engineering知识工程的发展 1、前知识工程时期——1950-1970时期:图...

头部AI社区如有邀博主AI主题演讲请私信—心比天高,仗剑走天涯,保持热爱,奔赴向梦想!低调,专注,谦虚,自律,反思,成长,还算比较正能量的博主,公益免费传播…内心特别想在AI界做出一些可以推进历史进程影响力的技术(兴趣使然,有点小情怀,也有点使命感呀 5336

栈和队列简介

栈和队列是插入和删除操作受阻的线性表栈:先进后出只能插入在表尾,删除时先删最后一个元素(表尾元素)队列:先进先出只能插入在表尾,删除时先删第一个元素(表头元素)存储结构:用顺序栈或链栈存储均可,但以顺序栈更常见逻辑结构:与线性表相同,仍为一对一关系存储结构:顺序队或链队,以循环顺序队列更常见逻辑结构:与线性表相同,仍为一对一关系约定an为栈顶,a1为栈底基本操作:初始化、入栈、出栈、销毁、清空、取栈顶元素等表尾即an端称为队尾,表头即a1端,称为队头。

lhr056813的博客 1430

高频电磁场仿真-主题064-伴随变量法与灵敏度分析

在电磁器件优化设计中,梯度信息对于指导优化方向至关重要。考虑一个典型的电磁优化问题: 其中 p=[p1,p2,...,pn]Tp = [p_1, p_2, ..., p_n]^Tp=[p1​,p2​,...,pn​]T 是设计参数向量(如几何尺寸、材料参数等)。传统有限差分法的困境:示例: 一个具有100个设计参数的天线优化问题伴随变量法(Adjoint Variable Method, AVM)通过引入伴随场,将梯度计算复杂度从 O(n)O(n)O(n) 降低到 O(1)O(1)O(1):伴随变量法在计算

kkchenjj的博客 413

后仿真中《SDF反标必懂连载篇》之 <INTERCONNECT/IOPATH> 到底反标电路路径是哪里

对于SDF INTERCONNECT ENTRY 描述,我们在之前的文章有详解。读万卷书,行万里路。实践很重要。今天,搞一下SDF INTERCONNECT / IOPATH 延迟数据信息,究竟反标的是哪一路径延时?究竟在电路上一段段如何表现出延迟现象的呢?

那么菜的博客 2139

数据结构栈和队列

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作,,栈中的数据元素遵守LIFO(last in first out)的原则压栈:栈的插入操作叫做进栈/压栈/入栈,出站栈:栈的删除操作叫做出栈,

ZerO_on的博客 883

2021.02.23丨Virsorter2安装使用及答疑

最近项目比较多,又在学英语,写文章的时间少了很多。最近接到一个病毒组装的项目。用之前组装工具(ABYSS、SPAdes)都没有能够组装较为完整的scafford,今天介绍一款专门用于组装病毒的工具——Virsorter。 Virsorter最早版本发布于2015年,目前已经有了第二个版本。主要用于病毒的组装的注释。详细情况可以查看文章:https://peerj.com/articles/985/ 安装流程 安装文档: https://github.com/jiarong/VirSorter2/b

4836

栈和队列的应用

栈和队列的题目解析

2402_82658387的博客 803

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

栈和队列特别篇:栈和队列的经典算法问题

栈和队列特别篇:栈和队列的经典算法问题(保姆级教程)

ChrisJamesljl的博客 1673

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

栈和队列的转化

栈与队列的相互转换栈和队列是两种基本的数据结构,它们在许多算法和程序中都有应用。虽然栈和队列在概念上是完全不同的,但是我们可以使用两个栈来实现一个队列,或者使用两个队列来实现一个栈。这种转换在某些情况下可能非常有用,例如,当我们的编程环境只提供了栈或队列的实现,但我们需要使用另一种数据结构时。在这篇博客中,我们将详细介绍如何使用两个栈来实现一个队列,以及如何使用两个队列来实现一个栈。我们将提供详细的代码示例,并解释每个函数的工作原理。提示:以下是本篇文章正文内容,下面案例可供参考。

xiaobai230811的博客 1551

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

【Java】栈和队列

本文主要介绍了栈、队列和循环队列的基本概念与实现。同时,通过对其模拟实现进一步了解其底层实现;

qq_51914226的博客 1009

栈和队列学习总结

一、栈 1、特点及应用 先进后出。(如果会和队列先进先出记混的话,就记场景吧:弹栈弹栈,就是把最上面的最新进来的弹出去;而队列就像我们火车站排队检票出站一样,谁排在前面谁就先出去。) 应用的话,其实我们经常接触呀。比如Undo操作(就是撤销操作)就是使用的栈的思想,以及程序调用的系统栈。下面我们举一个经典的括号匹配的例子: 题目要求: 给定一个只包括...

Marmara 1万+

栈和队列算法题

在学习了栈和队列的相关概念并且在之前也实现了栈和队列,接下来我们就来试着写一些栈和队列的算法题,在这些算法题当中将会使用到之前实现的栈或者队列,栈、队列在这当中将会变为工具一样,我们就会像工具一样拿着它们去解决问题,相信通过本篇算法题的解决,你会对栈和队列有更深层次的理解,一起加油吧!

mljy.博客 1552

栈和队列详解

栈只允许在栈顶进行操作,即插入数据在栈顶,出数据(删除)也在栈顶。这便是栈的结构,入栈和出栈都在栈顶进行。用数组实现栈的结构如上图所示,当然上图所展示的只是静态栈的结构,静态栈还是有许多缺点的,最为严重的就是空间的浪费,所以我们使用动态顺序表来是实现栈。代码: _a为数组,由我们自己动态申请空间,_top指向栈顶,_capacity为数组的容量。代码: 这里将_top初始化为0,也有将_top初始化为-1的,他们直接的区别就在于当栈为空时,_top所指向的地方不同,_top为0时指向a[0],_to

zjxuec的博客 1008

栈和队列的实现

啥是栈?啥是队列?你想知道的这里都有

xbhinsterest11的博客 2197

【数据结构】栈和队列

本文系统介绍了栈和队列两种基础数据结构。栈遵循"先进后出"原则,仅允许在固定端进行插入和删除操作;队列遵循"先进先出"原则,在一端插入,另一端删除。文章详细分析了双端队列和循环队列的实现原理,包括角标移动公式、有效长度计算等核心算法。同时比较了链表和数组两种实现方式的复杂度差异,并展示了Java集合框架中Stack类和Queue接口的具体使用方法。通过限制操作方式,任何线性结构都能实现栈或队列的特性,为程序设计提供了灵活的数据组织工具。

2503_92883549的博客 1181

【Leetcode】队列实现栈和栈实现队列

【Leetcode】队列实现栈和栈实现队列

旋律 | 话语 | 色彩 | 情景 1034

用队列实现栈和用栈实现队列

用队列实现栈和用栈实现队列

Jambo!的博客 464
上一篇: 监控Kafka集群
下一篇: 链表
炒栗子不加糖
博客等级 码龄10年 68粉丝 123原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值