【Java数据结构】线性表之栈和队列

news2024/12/23 3:31:57

栈(Stack)

简单描述

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。

压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。

出栈:栈的删除操作叫做出栈。出数据在栈顶。

 使用栈的一些常见的方法

压栈、出栈、获取栈顶元素、获取栈中元素个数、检查栈是否为空

public class Main {
    public static void main(String[] args) {
        Stack<Integer> stack = new Stack<>();
        stack.push(1);//压栈
        stack.push(2);
        stack.push(3);
        stack.peek();//获取栈顶元素
        stack.pop();//删除栈顶元素
        stack.size();//获取栈中元素的个数
        stack.empty();//判断栈是否为空
    }
}

使用数组模拟实现栈

public class MyStack {
    private int[] elem;
    private int usedSize;
    private static final int DEFAULT_CAPACITY = 10;

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

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

    private boolean checkCapacity(){
        if(this.usedSize == elem.length){
            return true;
        }
        return false;
    }

    public void push(int val){
        if(this.checkCapacity()){
            this.elem = Arrays.copyOf(this.elem,2*this.elem.length);
        }
        this.elem[this.usedSize] = val;
        this.usedSize++;
    }

    public int pop() throws EmptyException {
        if(this.usedSize == 0){
            //throw new EmptyException("栈为空!");
            return -1;
        }
        int tmp = this.elem[this.usedSize-1];
        this.usedSize--;
        return tmp;
    }

    public int peek() throws EmptyException {
        if(this.usedSize == 0){
            //throw new EmptyException("栈为空!");
            return -1;
        }
        int tmp = this.elem[this.usedSize-1];
        return tmp;
    }
    
    public int size(){
        return this.usedSize;
    }
    
    public boolean empty(){
        return this.usedSize == 0;
    }
}

我们使用 usedSize 来记录栈中元素的个数,压栈的时候就在 elem[usedSize] 输入元素,出栈的时候 usedSize 减一就可以了。

为什么用数组来实现栈? 因为用数组来实现栈的时间复杂度为 O(1) 比较高效。

从上图中可以看到,Stack继承了Vector,Vector和ArrayList类似,都是动态的顺序表,不同的是Vector是线程安全的 。

逆序输出链表

我们知道栈的一个特点是先进后出,那么先放进去的元素最后出栈。因此我们就可以达到一个目的:逆序

我们知道一个逆序的方法:递归

void printList(Node head){
   if(null != head){
       printList(head.next);
       System.out.print(head.val + " ");
  }
}

接下来我们利用栈来实现逆序:

void printList(Node head){
   if(null == head){
       return;
  }
   Stack<Node> s = new Stack<>();
   // 将链表中的结点保存在栈中
   Node cur = head;
   while(null != cur){
       s.push(cur);
       cur = cur.next;
  }

   // 将栈中的元素出栈
   while(!s.empty()){
       System.out.print(s.pop().val + " ");
  }

队列(Queue)

简单描述

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(FirstIn First Out) 入队列:进行插入操作的一端称为队尾(Tail/Rear) 出队列:进行删除操作的一端称为队头(Head/Front) 。

在Java中,Queue是个接口,底层是通过链表实现的。

队列(Queue)的一些常见方法

入队、出队、获取队头元素、获取队中元素个数、判断队列是否为空

public class Main {
    public static void main(String[] args) {
        Queue<Integer> queue = new LinkedList<>();
        queue.offer(1);//入队
        queue.offer(2);
        queue.offer(3);
        queue.poll();//删除队头元素
        queue.peek();//获取队头元素
        queue.size();//获取队中元素个数
        queue.isEmpty();//判断队列是否为空
    }
}

使用链式结构来模拟实现队列

我们模拟实现队列既可以用线性结构也可以用链式结构,接下来我们使用链式结构来模拟实现一个简单队列。

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

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

    private ListNode front;//队头
    private ListNode rear;//队尾

    public void offer(int data){
        ListNode node = new ListNode(data);
        if(front == null){
            front = rear = node;
        }else{
            node.next = front;
            front.prev = node;
            front = node;
            this.usedsize++;
        }
    }

    public int poll(){
        if(front == null){
            System.out.println("队列没有元素!");
            return -1;
        }
        if(front == rear){
            int b = this.rear.val;
            front = null;
            rear = null;
            this.usedsize--;
            return b;
        }
        int a = this.rear.val;
        this.rear.prev.next = null;
        this.usedsize--;
        return a;
    }

    public int peek(){
        if(front == null){
            System.out.println("队列没有元素!");
            return -1;
        }
        if(front == rear){
            int b = this.rear.val;
            return b;
        }
        int a = this.rear.val;
        return a;
    }

    public int size(){
        return this.usedsize;
    }

    public boolean isEmpty(){
        return this.usedsize == 0;
    }
}

这里我们 offer 入队操作采用的是链表中的头插法,我们使用双向链表的操作使得我们可以保存尾节点的位置,利于我们可以直接进行删除操作。

循环队列

上面我们提到还可以使用线性结构来实现队列。但是这时就有一个问题了,我们使用数组来达到队列的效果,在进行删除操作的时候,尾节点慢慢向前,会造成假溢出的现象。这时我们就要引入循环队列的概念。

此时我们在进行入队和出队操作的时候就不能单纯的使用 front++ 和 rear++ 不然我们达不到循环的效果。我们应该使用 (front+1)%elem.length 和 (rear+1)%elem.length 来控制头节点和尾节点的移动。

判断队空和队满

三种方法:

  • 1. 通过添加 size 属性记录
  • 2. 保留一个位置
  • 3. 使用标记

1.我们从一开始就定义一个 size 来记录队列中元素的个数,当 size == 0 的时候队空 ,当 size == elem.length 的时候队满。

2.我们保留一个位置不放元素,当 front == rear 的时候队空,当 ((rear+1)%elem.length+1)elem.length == front 的时候队满。

3.我们使用一个 flag 来充当标记,开始的时候 front == rear 这时 flag = 0 队为空,当再次遇到 front == rear 的时候将 flag = 1 这时队满。

双端队列

双端队列(deque)是指允许两端都可以进行入队和出队操作的队列,deque 是 “double ended queue” 的简称。那就说明元素可以从队头出队和入队,也可以从队尾出队和入队。

Deque是一个接口,使用时必须创建LinkedList的对象。

 由于该队列的特点:元素可以从队头出队和入队,也可以从队尾出队和入队。因此双端队列既可以充当栈来使用也可以充当普通队列来使用。

 在实际工程中,使用Deque接口是比较多的,栈和队列均可以使用该接口。

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

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

相关文章

DETR算法解读——Transformer在目标检测任务的首次应用

论文&#xff1a;End-to-End Object Detection with Transformers 作者&#xff1a;Nicolas Carion, Francisco Massa, Gabriel Synnaeve, Nicolas Usunier, Alexander Kirillov, Sergey Zagoruyko 机构&#xff1a;Facebook AI 链接&#xff1a;https://arxiv.org/abs/2005.12…

【网络】网络基础(框架)

网络基础 序言&#xff1a;什么是网络&#xff1f;一、协议的概念二、网络位置三、网络协议1、协议分层2、OSI七层模型与TCP/IP五层(或四层)模型 四、网络传输基本流程1、网络传输流程图2、以太网通信&#xff08;1&#xff09;一个小故事&#xff08;2&#xff09;原理i、问题…

解答word图标变白

把WPS卸载了之后就变成白色了&#xff0c;然后在注册表中把word的地址改成office word的地址之后图标变成这样了&#xff0c;怎么办 1.winR打开命令提示符 2.输入regedit&#xff0c;打开注册表编辑器 3.找到下面这个路径 计算机\HKEY_CLASSES_ROOT\Word.Document.8\Defaul…

从零开始学量化~Ptrade使用教程(七)——期权相关操作

期权交易 可点击证券代码右侧的选&#xff0c;进入期权选择菜单。通过选择标的商品&#xff0c;认购期权和认沽期权中间的选项&#xff08;包括代码、成交价、幅度%、隐波%、内在价值、时间价值等&#xff09;&#xff0c;以及认购期权或认沽期权&#xff0c;选择所需的期权标的…

2024年第二季度 DDoS 威胁趋势报告

2024 年上半年&#xff0c;Cloudflare 缓解了 850 万次 DDoS 攻击&#xff1a;第一季度 450 万次&#xff0c;第二季度 400 万次。总体而言&#xff0c;第二季度 DDoS 攻击数量环比下降了 11%&#xff0c;但同比增长了 20%。 DDoS 攻击分布&#xff08;按类型和手段&#xff09…

pycharm中运行.sh文件

最近在跑一个项目代码&#xff0c;里面要运行.sh文件。于是配置了下如何在pycharm中正常运行.sh文件。 首先安装好git&#xff0c;然后 File—>Settings—>Tools—>Terminal—>Shell path&#xff0c;将cmd.exe改成刚刚下载的git的路径&#xff0c;注意选择的是s…

【MySQL进阶之路 | 高级篇】EXPLAIN的进一步使用

1. EXPLAIN的四种输出格式 EXPLAIN可以输出四种格式&#xff1a;传统格式&#xff0c;JSON格式&#xff0c;TREE格式以及可视化输出。用户可以根据需要选择使用于自己的格式。 1). 传统格式 传统格式简单明了&#xff0c;输出是一个表格形式。 2). JSON格式 第一种格式中介…

wireshark抓包语法

主要功能 Wireshark 的主要功能包括&#xff1a; 实时数据捕获&#xff1a;能够捕获实时流量并对其进行分析。数据包解码&#xff1a;支持数百种网络协议&#xff0c;能够解码并显示各种协议的详细信息。过滤功能&#xff1a;提供强大的过滤功能&#xff0c;可以根据特定条件…

esp32c2-ble-2mb-at,蓝牙AT固件获取方法

文章目录 1. 背景2. 本地编译3. 环境安装依赖包下载1. 背景 最近在做一个数据透传项目,买了一块ESP32-C2 2MB的开发板,WIFI透传串口数据功能调通了(感兴趣的小伙伴可以了解下ESP32-C2模组数据透传模式配置详细教程),想试试蓝牙透传,官方给出的说法是BLE固件未发布,可以从…

项目收获总结--大数据量存储架构设计方案

项目收获总结--大数据量存储架构设计方案 一、背景二、数据存储层技术选型2.1 MySQL2.2 MongoDB2.3 HBase2.4 HBaseElasticSearch 三、HBaseElasticSearch基本原理3.1 前置考虑3.2 HBaseElasticSearch优点3.3 HBaseElasticSearch缺点 四、HBaseElasticSearch数据一致性架构4.1 …

A Survey on Multimodal Large Language Models综述

论文题目:A Survey on Multimodal Large Language Models 论文地址:https://arxiv.org/pdf/2306.13549 话题:多模态LLMs综述 MLLMs Paper: https://github.com/BradyFU/Awesome-Multimodal-Large-Language-Models 1. 摘要 近期,以GPT-4V为代表的跨模态大型语言模型(MLLM…

vue3前端开发-小兔鲜项目-人气推荐栏目的前端渲染

vue3前端开发-小兔鲜项目-人气推荐栏目的前端渲染&#xff01;今天和大家分享一下&#xff0c;人气推荐栏目的前端页面如何渲染内容。 经历过上一次的&#xff0c;新鲜好物的栏目渲染之后&#xff0c;我们已经熟练了&#xff0c;vue3的接口调用&#xff0c;数据渲染到页面中的整…

Zabbix监控介绍与部署

目 录 一、zabbix介绍和架构 1.1 zabbix介绍 1.2 为什么需要监控 1.3 需要监控什么 二、zabbix使用场景与系统概述 2.1 zabbix的功能 2.2 zabbix架构 2.3 Zabbix术语 三、编译安装zabbix 3.1 安装依赖环境 3.2 建立管理用户 3.3 准备源码包&#xff0c;解压包 3.…

数据结构初阶-单链表

链表的结构非常多样&#xff0c;以下情况组合起来就有8种&#xff08;2 x 2 x 2&#xff09;链表结构&#xff1a; 而我们主要要熟悉的单链表与双向链表的全称分别为&#xff1a;不带头单向不循环链表&#xff0c;带头双向循环链表&#xff0c;当我们对这两种链表熟悉后&#x…

基于python深度学习遥感影像地物分类与目标识别、分割实践技术应用

目录 专题一、深度学习发展与机器学习 专题二、深度卷积网络基本原理 专题三、TensorFlow与Keras介绍与入门 专题四、PyTorch介绍与入门 专题五、卷积神经网络实践与遥感图像场景分类 专题六、深度学习与遥感图像检测 专题七、遥感图像检测案例 专题八、深度学习与遥感…

【教学类-68-01】20240720裙子涂色(女孩篇)

背景需求&#xff1a; 通义万相下载了简笔画裙子&#xff0c;制作成涂色卡给幼儿涂色、剪纸用。 代码展示 裙子简笔画图 6张 星火讯飞、通义万相、阿夏 2024年7月20日import os,time import shutil from docx import Document from docx.shared import Cm from PIL import Ima…

ApolloAndroid 使用笔记

由于业务需求的变化&#xff0c;需要使用 Graphql 作为客户端与服务端的交互查询框架&#xff0c;特此记录使用。 测试代码下载链接 一、导入引用以及规则示例 1、首先需要在我们需要使用的模块下面创建对应的src/main/graphql文件夹 2、将后台对应的服务生成的 xxx.graphql…

1个Xpath定位可以在Web页面查找到多个元素Selenium

1个Xpath定位可以在Web页面查找到多个元素Selenium//input[id\"transactionId\"] 打开Web页面&#xff0c; 点击F12可以看到压面 点击Ctrl F 可以点图如下图的输入框&#xff0c;输入xpath&#xff0c;看右侧可以找到3个对应的元素 点击Ctrl F 点击Ctrl F 点…

【C语言】逗号运算符详解 - 《不起眼的 “逗号”》

目录 C语言逗号运算符详解1. 逗号运算符的定义1.1 基本语法1.2 执行顺序 2. 逗号运算符的用法2.1 用于循环2.1.1 示例 2.2 用于表达式组合2.2.1 示例 3. 逗号运算符的应用场景3.1 宏定义3.1.1 示例 3.2 条件运算符中的应用3.2.1 示例 4. 总结5. 参考文献6. 结束语 C语言逗号运算…

通信网络机房服务器搬迁流程方案

数据中心机房搬迁是一项负责高难度的工程。整个搬迁过程充满挑战&#xff0c;伴随着各种风险。如何顺利的完成服务器的迁移&#xff0c;需要专业的数据中心服务商全程提供保障。友力科技&#xff08;广州&#xff09;有限公司&#xff0c;作为华南地区主流的数据中心服务商&…