详解栈和队列

news2024/9/22 13:36:23

目录:

1.栈

2.队列

一、 栈(Stack)

1.1 概念:

栈是一种特殊的线性表,只允许在固定的一端进行插入和删除元素的操作。进行插入元素的一端叫做栈顶,另一端叫做栈底。从数据结构的角度出发,栈中的元素遵循先进后出的原则。

1.2 栈的内在方法:

Stack():

Stack的构造方法,用来创建一个栈类型的对象。

由于栈是一个泛型类,所以在创建对象时可以传入类型实参以规定栈中存储的数据类型。

Stack stack1 = new Stack();

Stack<Integer> stack2 = new Stack<>();

push(E):

入栈,并且返回该元素的值。

public static void main(String[] args) {
        Stack<Integer> stack = new Stack<>();
        System.out.println(stack.push(1));
    }


//运行结果:1

如果使用了<>,就必须放规定类型的数据;如果没有用<>,可以往栈中存入任意类型的数据。 

pop():

出栈,并返回该元素的值。

public static void main(String[] args) {
        Stack<Integer> stack = new Stack<>();
        stack.push(1);
        System.out.println(stack.pop());
    }


//运行结果:1

如果空栈进行出栈,则会抛出异常。

peek():

仅返回栈顶元素的值。

public static void main(String[] args) {
        Stack<Integer> stack = new Stack<>();
        stack.push(1);
        System.out.println(stack.peek());
    }



//运行结果:1

如果对空栈进行peek,就会抛出异常。

empty():

返回该栈是否为空。

        Stack<Integer> stack = new Stack<>();
        stack.push(1);
        System.out.println(stack.empty());


//运行结果:false

        Stack<Integer> stack = new Stack<>();
        System.out.println(stack.empty());


//运行结果:true

 1.3 模拟实现栈:

链栈:

用链表实现栈。

如果链表采用尾插的话,push的时间复杂度为O(1),pop的时间复杂度为O(N);

如果链表采用首插的话,push的时间复杂度为O(1),pop的时间复杂度为O(1),所以采用首插。

public class List_stack {
    ListNode head;

    static class ListNode{
        ListNode next;
        int a;
    }

    public void push(ListNode l) {
        if (l == null) {
            return;
        }
        l.next = head;
        head = l;
    }

    public ListNode pop(){
        ListNode k = head;
        try {
            if (head == null) {
                throw new EmptyException();
            }
            head = head.next;
        }catch (EmptyException o){
            o.printStackTrace();
        }
        return k;
    }

    public ListNode peek() {
        return head;
    }

    public boolean isEmpty() {
        return head == null;
    }
}

顺序栈:

用顺序表实现栈。

如果顺序表采用尾插的话,push的时间复杂度为O(1),pop的时间复杂度为O(1);

如果顺序表采用首插的话,push的时间复杂度为O(N),pop的时间复杂度为O(N),所以采用尾插。

public class MyStack {
    public int[] elem;
    public int usedSize;

    public MyStack(int[] elem) {
        this.elem = new int[10];
    }

    public void push(int date) {
        if (isFull()) {
            elem = Arrays.copyOf(elem, 2 * usedSize);
        }
        elem[usedSize++] = date;
    }

    public boolean isFull() {
        return usedSize == elem.length;
    }

    public int pop() {
        try {
            if (isEmpty()){
                throw new EmptyException("栈为空");
            }
        }catch (EmptyException e) {
            e.printStackTrace();
        }
        return elem[--usedSize];
    }

    public int peek() {
        try {
            if (isEmpty()){
                throw new EmptyException("栈为空");
            }
        }catch (EmptyException e) {
            e.printStackTrace();
        }
        return elem[usedSize - 1];
    }
    public boolean isEmpty() {
        return usedSize == 0;
    }
}

二、 队列(Queue)

1.1 概念:

队列是只允许在一端进行插入数据,在另一端删除数据的特殊线性表,具有先进先出(FIFO)的特点。

与栈有所不同,队列在Java中是一个接口,以链表为底层实现的。

1.2 队列的内在方法:

add(E):

将指定元素添加到队列中

  • 如果元素成功添加,始终返回 true(对于没有容量限制的队列)。如果无法添加元素,该方法会抛出异常。

offer(E):

尝试立即将指定元素添加到队列中,前提是不违反容量限制。

  • 成功添加元素则返回 true
  • 由于容量限制无法添加元素则返回 false

remove():

检索并移除队列的头部元素,返回队列的头部元素。

poll():

检索并移除队列的头部元素。

  • 返回队列的头部元素,若队列为空则返回 null

element():

检索但不移除队列的头部元素,返回队列的头部元素。

peek():

检索但不移除队列的头部元素。

  • 返回队列的头部元素,若队列为空则返回 null

总结

  • 添加元素:使用 offer() 处理容量受限的队列,使用 add() 处理没有容量限制的队列。
  • 移除元素:使用 poll() 安全地移除元素,若队列为空则返回 null,使用 remove() 在队列为空时抛出异常。
  • 查看元素:使用 peek() 安全地查看队列头部元素,若队列为空则返回 null,使用 element() 在队列为空时抛出异常。

1.3 模拟实现队列:

public class MyQueue {
    static class ListNode{
        ListNode prev;
        ListNode next;
        int val;

        public ListNode(int val) {
            this.val = val;
        }
    }

    ListNode first;
    ListNode last;

    public void offer(int val) {
        ListNode cur = new ListNode(val);
        if (first == null) {
            last = cur;
            first = cur;
        }else {
            last.next = cur;
            cur.prev = last;
            last = last.next;
        }
    }

    public int poll() {
        if (isEmpty()) {
            return -1;
        }
        int k = first.val;
        first = first.next;
        if (first != null) {
            first.prev = null;
        }
        return k;
    }

    public int peek() {
        if (isEmpty()) {
            return -1;
        }
        return first.val;
    }

    public boolean isEmpty() {
        return first == null;
    }
}

1.4 循环队列:

循环队列一般是数组实现的,有两个难点:

1. 怎么使下标循环;

(index + 1)% elem.length就是走一步。

2. 怎么判断元素放满了。

有三种方法:1. 使用一个变量进行标记;

                      2. 使用size来储存数据的个数与数组长度进行对比;

                      3. 浪费一个空间,当pos2走一步之后判断是否等于pos1。 


public class CirQueue {
    int first;
    int last;
    int[] elem;

    public CirQueue() {
        elem = new int[8];
    }

    public void push(int val) {
        if (isFull()) {
            return;
        }
        elem[last % 8] = val;
        last++;
    }

    public int pop() {
        if (isEmpty()) {
            return -1;
        }
        int k = elem[first];
        first = (first + 1) % 8;
        return k;
    }

    public int peek() {
        if (isEmpty()) {
            return -1;
        }
        return elem[first];
    }

    public boolean isEmpty() {
        return last == first;
    }

    public boolean isFull() {
        return (last + 1) % 8 == first;
    }
}

 1.5 双端队列(Deque):

1.6 用队列实现栈:

一个队列是不能实现的,所以我们需要两个,如果我们要删除最后进入的数据,我们需要先将上面的元素出队并且存入另一个队列中,最后才能将队尾元素删除或检索。

public class Q_stack {
    Queue<Integer> queue1;
    Queue<Integer> queue2;
    public Q_stack() {
        queue1 = new LinkedList<>();
        queue2 = new LinkedList<>();
    }

    public void push(int x) {
        if (empty()) {
            queue1.offer(x);
        }else if (!queue2.isEmpty()) {
            queue2.offer(x);
        }else {
            queue1.offer(x);
        }
    }

    public int pop() {
        if (empty()) {
            return -1;
        }else if (!queue2.isEmpty()) {
            for (int i = 0; i < queue2.size() + queue1.size() - 1; i++) {
                queue1.offer(queue2.poll());
            }
            return queue2.remove();
        }else {
            for (int i = 0; i < queue1.size() + queue2.size() - 1; i++) {
                queue2.offer(queue1.poll());
            }
            return queue1.remove();
        }
    }

    public int top() {
        int k = 0;
        if (empty()) {
            return -1;
        }else if (!queue2.isEmpty()) {
            for (int i = 0; i < queue2.size() + queue1.size(); i++) {
                k = queue2.element();
                queue1.offer(queue2.poll());
            }
            return k;
        }else {
            for (int i = 0; i < queue1.size() + queue2.size(); i++) {
                k = queue1.element();
                queue2.offer(queue1.poll());
            }
            return k;
        }
    }

    public boolean empty() {
        return queue1.isEmpty() && queue2.isEmpty();
    }
}

 

1.7 用栈实现队列:

把stack1作为存放数据的栈,把stack2作为操作数据的栈,当stack2为空时将stack1中的数据转移到stack2。

public class S_queue {
    Stack<Integer> stack1;
    Stack<Integer> stack2;

    public S_queue() {
        stack1 = new Stack<>();
        stack2 = new Stack<>();
    }

    public void push(int val) {
        stack1.push(val);
    }

    public int pop() {
        if (stack2.isEmpty()) {
            while (!stack1.isEmpty()) {
                stack2.push(stack1.pop());
            }
        }
        return stack2.pop();
    }

    public int peek() {
        if (stack2.isEmpty()) {
            while (!stack1.isEmpty()) {
                stack2.push(stack1.pop());
            }
        }
        return stack2.peek();
    }

    public boolean isEmpty() {
        return stack1.isEmpty() && stack2.isEmpty();
    }
}

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

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

相关文章

k8s-deployment控制器

k8s-deployment控制器 1、yaml文件标签学习-指定pod在哪台节点上创建 强制指定pod在指定节点上创建&#xff1a; --- apiVersion: apps/v1 kind: Deployment metadata:name: my-deployment spec:replicas: 3selector:matchLabels:app: web1template:metadata:labels:app: web1…

流媒体服务器二 3学习 librtmp 库的配置使用

librtmp 库是个啥&#xff1f; librtmp是一个开源的基于C语言的库&#xff0c;提供了一个连接RTMP服务器&#xff0c;发送和接收RTMP流的API。 它可以用来开发流媒体播放器&#xff0c;网络直播等应用。它的主要特点是快速、稳定和低延迟。 librtmp支持RTMP&#xff0c;RTMPS…

超越 RAG 基础:AI 应用的高级策略

作者&#xff1a;来自 Elastic Platform Team 我们最近与 Cohere 举办的线上活动深入探讨了检索增强生成 (Retrieval Augmented Genereation - RAG) 的世界&#xff0c;重点讨论了在概念验证阶段之后构建 RAG 应用程序的关键注意事项。我们的演讲者是 Elastic 的首席解决方案架…

使用 Python和 FFmpeg 批量截图视频到各自文件夹中

在这篇博客中&#xff0c;我们将创建一个简单的图形用户界面 (GUI) 工具&#xff0c;利用 wxPython 和 FFmpeg 来从视频文件中批量生成截图。这个工具能够让用户选择一个文件夹&#xff0c;遍历其中的所有视频文件&#xff0c;按照视频长度将其分为四等分&#xff0c;然后为每个…

鸿蒙HarmonyOS之使用ArkTs语言实现自定义Tab菜单栏分页主页面UI

一、效果 显示为3个Tab菜单栏&#xff0c;中间可以滑动 二、实现步骤 1、Index.ets 示例代码中用到的颜色、文字、图片等资源可以自行替换 import { Tab_1 } from ./Tab_1; import { Tab_2 } from ./Tab_2; import { Tab_3 } from ./Tab_3;//主页面 Entry Component stru…

Excel数字中间指定位置插入符号——以120120加*为例

设置单元格格式——自定义 更多阅读Excel数字中间指定位置插入符号_哔哩哔哩_bilibili

B码对时案例分享,基于RK3568J+Logos-2,让电力设备轻松实现“高精度授时”!

本文主要介绍瑞芯微RK3568J紫光同创Logos-2的B码对时案例&#xff0c;开发环境如下&#xff1a; Windows开发环境&#xff1a;Windows 7 64bit、Windows 10 64bit Pango Design Suite(PDS)&#xff1a;PDS_2022.2-SP3 IRIG-B码对时典型应用 IRIG-B码对时可应用于继电保护装…

台球厅自动控制无人台球之智能开关-SAAS本地化及未来之窗行业应用跨平台架构

一、无人台球厅优点 1. 降低人力成本&#xff1a;无需雇佣大量员工&#xff0c;如收银员、服务员等&#xff0c;节省了工资、福利和管理成本。 2. 24 小时营业&#xff1a;不受人工营业时间限制&#xff0c;可以随时满足顾客的需求&#xff0c;增加营业时长和收入。 3. 便捷高…

不良图片检测

OpenNSFW模型简介 OpenNSFW是一个由 Yahoo 研究院开源的深度学习模型&#xff0c;用于识别和区分网络上的正常内容与不适宜内容&#xff08;Not Safe For Work&#xff09;。 项目地址&#xff1a;https://github.com/yahoo/open_nsfw OpenNSFW主要基于Caffe框架实现&#x…

邮票孔拼版制作方法

邮票孔拼版制作方法 拼版后的局部图:(中间用连接桥的方式&#xff0c;此方式能最少程度上减少残留) 2&#xff09;拼版后的效果图 3&#xff09;邮票孔拼版规则: 拼板与板间距1.2MM或者1.6MM 等邮票孔&#xff1a;8个0.55MM的孔,孔间距0.2MM加两排&#xff0c;邮票孔伸到…

KubeSphere核心实战_kubesphere部署redis01_为redis指定配置文件_指定存储卷_配置服务---分布式云原生部署架构搭建047

然后我们再来,部署一下redis,可以看到,首先去容器官网去找到对应的redis的镜像然后 可以看到镜像中都有说的,如何启动,以及 --appendonly yes 是指定持久化.然后 /data表示数据存储的位置. 可以看到数据存储位置 然后还有配置文件的位置. 可以看到,我们首先去创建配置文件,然后…

【专题】2024全数驱动 致胜未来-数字化敏捷银行白皮书报告合集PDF分享(附原数据表)

原文链接&#xff1a; https://tecdat.cn/?p37404 政策明确发展使命&#xff0c;新时代商业银行应坚持党建引领&#xff0c;秉持高质量发展理念。数字经济已成大势&#xff0c;商业银行需构建数字基础设施能力&#xff0c;强化顶层战略规划。当前商业银行数字化发展面临诸多挑…

改变自己·心情治愈

今早起床了 看镜子里的我 忽然发现我发型睡得有点kuso 一点点改变&#xff0c;有很大的差别 你我的力量也能改变世界 最近比较烦 最近情绪很down 每天看新闻都会很想大声尖叫 但脏话没用 大家只会嫌凶 我改变自己发现大有不同 新一代的朋友我们好好地加油 大家一起大…

QT:QWebEngineView基本使用

QWebEngineView介绍 添加库 QT core gui webenginewidgets出现问题 解决 提升类 Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);//ui->web_widget->load(QUrl("http://www.baidu.com"));ui->…

Rimworld边缘世界使用服务器开服联机教程

订阅联机模组RimWorld Together (MULTIPLAYER)&#xff08;百度莱卡云&#xff09; 打开创意工坊搜索RimWorld Together (MULTIPLAYER) 订阅联机模组与它的依赖模组 打开游戏➡点击Mod配置 双击左边灰色的模组&#xff0c;到右边启用 还需要排一下顺序&#xff0c;顺序不对会…

iPhone变身万能钥匙,iOS 18.1让你的手机解锁一切

Apple 近日发布新闻稿宣布&#xff0c;在即将推出的 iOS 18.1 更新中&#xff0c;将开放全新的 NFC&#xff08;近场通信&#xff09;和 SE&#xff08;安全元件&#xff09;API 给第三方开发者使用。这一举措将使得开发者能够开发出更加多样化和实用的应用程序&#xff0c;如车…

Redis清空缓存

Windows环境下使用命令行进行redis缓存清理 1、redis安装目录下输入cmd 2、redis-cli -p 端口号 3、flushdb 清除当前数据库缓存 4、flushall 清除整个redis所有缓存

Dubbo源码深度解析(七)

接上一篇博客《Dubbo源码深度解析(六)》&#xff0c;上篇博客主要从服务消费方开始讲起&#xff0c;主要讲&#xff1a;如果类中的属性或者方法&#xff0c;如果被DubboReference注解所修饰&#xff0c;Dubbo是怎么处理的&#xff0c;处理逻辑类似Spring框架提供的Autowired注解…

JavaScript - Ajax

Asynchronous JavaScript And XML&#xff0c;异步的JavaScript和XML 作用: 数据交换&#xff1a;通过Ajax可以给服务器发送请求&#xff0c;并获取服务器响应的数据。异步交互&#xff1a;可以在不重新加载整个页面的情况下&#xff0c;与服务器交换数据并更新部分网页的技术…

Vue2 与 Vue3 生命周期对比

首先我们需要了解 Vue2 的生命周期&#xff0c;请参考我之前写的博文 Vue2-生命周期 Vue2 生命周期存在四个阶段&#xff0c;八个钩子函数&#xff0c;具体作用可以看图&#xff0c;详细解释可以参考之前的博文 Vue3 生命周期 经过对比&#xff0c;我们发现 Vue3 的生命周期也存…