数据结构——Java实现栈和队列

news2024/11/14 19:47:38

一、栈 Stack

1.特点

(1)栈是一种线性数据结构

(2)规定只能从栈顶添加元素,从栈顶取出元素

(3)是一种先进后出的数据结构(Last First Out)LIFO

2.具体实现

Java中可以直接调用方法来实现栈

如何自己写代码来实现栈呢?

先定义一个接口,方便后边进行调用

package com.algo.lesson.lesson02.stack;

public interface Stack_I<T> {
    //入栈
    void push(T ele);
    //出栈
    T pop();
    //查看栈顶元素
    T peek();
    //判断是否为空
    boolean isEmpty();
    //后去栈中元素
    int getSize();
}

接下来来实现栈的方法,调用接口,完善方法:

package com.algo.lesson.lesson02.stack;

import com.algo.lesson.lesson01.MyArr;

//以数组作为栈顶的底层数据结构
public class ArrStack<T> implements Stack_I<T> {

    private MyArr<T>data;

    int size;

    public ArrStack() {
        this.data=new MyArr<>(100);
        this.size=0;
    }

    @Override
    public void push(T ele) {
        //在数组尾部添加元素
        this.data.add(ele);
        this.size++;
    }

    @Override
    public T pop() {
        if(isEmpty()){
            return null;
        }
        this.size--;
        return this.data.removeBFromLast();
    }

    @Override
    public T peek() {
        return this.data.getLastValue();
    }

    @Override
    public boolean isEmpty() {
        return this.size==0;
    }

    @Override
    public int getSize() {
        return this.size;
    }
}

以上就是方法的代码,接下来,写个main函数来调用,检查方法是否正确

package com.algo.lesson.lesson02.stack;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class StackTest<T> {
    public void test(Stack_I<T>stack, List<T> list){
        //开始时间
        long startTime=System.nanoTime();

        for(int i=0;i<list.size();i++){
            stack.push(list.get(i));
        }
        System.out.println(stack.getSize());
        while(!stack.isEmpty()){
            T ele=stack.pop();
            System.out.println(ele+"  ");
        }

        //结束时间
        long endTime=System.nanoTime();
        System.out.println("总耗时:"+(endTime-startTime)/100000000.0);
    }

    public static void main(String[] args) {
        StackTest<Integer>stackTest=new StackTest<>();
        Stack_I<Integer>stack=new ArrStack<>();
        List<Integer>list=new ArrayList<>();
        Random random=new Random();
        for(int i=0;i<100;i++){
            int val= random.nextInt(1000);
            list.add(val);
        }
        stackTest.test(stack,list);
    }
}

注:其中long startTime=System.nanoTime();方法是获取一个时间(单位毫秒)

在程序运行前和运行后个添加一个,最后将两个时间相减,得到程序运行时间。

3.时间复杂度分析

二、队列

1.特点

(1)队列也是一种线性数据结构

(2)只能从一端添加元素,另一端取出元素

(3)是一种先进先出的数据结构(FIFO——fist in fist out )

2.具体实现

Java中也可以直接调用队列的方法:

自己的实现:

接口:

package com.algo.lesson.lesson02.queue;

public interface Queue_I<T> {
    void offer(T ele);//入队
    T poll();//出队
    T peek();//查找队首元素
    int getSize();
    boolean isEmpty();


}

方法代码:

package com.algo.lesson.lesson02.queue;

import com.algo.lesson.lesson01.MyArr;

public class ArrQueue<T>implements Queue_I<T> {

    private MyArr<T>data;

/*
    private int size;//队列中元素的个数
*/

    public ArrQueue(){
        this.data=new MyArr<>(50);
    }

    @Override
    public void offer(T ele) {
        this.data.add(ele);
    }

    @Override
    public T poll() {
        if(isEmpty()){
            return null;
        }
        return this.data.removeByIndex(0);
    }

    @Override
    public T peek() {
        if(isEmpty()){
            return null;
        }
        return this.data.getValueByIndex(0);
    }

    @Override
    public int getSize() {
        return this.data.getSize();
    }

    @Override
    public boolean isEmpty() {
        return this.data.isEmpty();
    }
}

3.出现的问题

入队列时间复杂度为O(n),因为在出队时,元素要前移,会出现假溢出的情况。

所以就出现了循环队列来解决这个问题

循环队列:

front记录队首,tail记录队尾,队尾达到容积时,返回到队头,将空位置补上,可以继续存储数据。

package com.algo.lesson.lesson02.queue;

import java.util.Random;

/*
基于Java中的数组进行二次封装,制作一个可变数组
 */
//泛型:就是类型作为参数
public class LoopArr<T> {
    private T[] data;//保存数据

    private int size;//数组中实际存放元素的个数

    private int front;//队首

    private int tail;//队尾

    int capacity;//容积

    //构造函数
    public LoopArr(int capacity) {
        if (capacity <= 0) {
            this.capacity = 11;
        } else {
            this.capacity = capacity + 1;
        }
        this.size = 0;
        this.front = this.tail = 0;
        this.data = (T[]) (new Object[this.capacity]);
    }

    //获取数组中实际存放元素的个数
    public int getSize() {
        return this.size;
    }

    //获取数组的容积
    public int getCapacity() {
        return this.capacity;
    }

    //判断数组是否为空
    public boolean isEmpty() {
        return this.front == this.tail;
    }

    //向数组中添加元素(尾部)
    public void add(T item) {
        //判断数组是否满
        if ((this.tail + 1) % this.capacity == this.front) {
            //扩容
            resize((this.capacity-1)*2+1);
        }
        //从index位置开始元素需要进行后移
        this.data[this.tail] = item;
        this.tail = (this.tail + 1) % this.capacity;
        //更新this.size
        this.size++;
    }

    private void resize(int newCapacity) {
        System.out.println("resize:" + newCapacity);
        T[] newData = (T[]) (new Object[newCapacity]);
        //将原数组驾到新数组里

        for (int i = 0; i < this.size; i++) {
            newData[i] = this.data[(this.front+i)%this.capacity];
        }
        //改变容器
        this.data = newData;
        this.capacity = newCapacity;
        //将this.front置零
        this.front=0;
        this.tail=this.size;
    }

    //获取指定位置的值
    public T getValueByIndex() {
        if(isEmpty()){
            return null;
        }
        return this.data[this.front];
    }

    //移除队首元素
    public T remove() {
        if (isEmpty()) {
            return null;
        }
        //删除操作的核心
        /*
        1.找到删除的位置
        2.删除位置之后的元素要前移 arr[j-1]=arr[j]
         */
        T delValue = this.data[this.front];
        this.front = (this.front + 1) % this.capacity;
        this.size--;
        //判断是否缩容
        if (this.size < this.capacity / 4 && this.capacity / 2 > 0) {
            resize((this.capacity-1) / 2 +1);
        }
        return delValue;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("[");
        for (int i = 0; i < this.size; i++) {
            sb.append(this.data[i]);
            if (i != this.size - 1) {
                sb.append(",");
            }
        }
        sb.append("]");
        return sb.toString();
    }
}
package com.algo.lesson.lesson02.queue;

public class LoopQueue<T> implements Queue_I<T>{

    private LoopArr<T>data;//容器

    public LoopQueue(){
        this.data=new LoopArr<>(100);
    }




    @Override
    public void offer(T ele) {
        this.data.add(ele);
    }

    @Override
    public T poll() {
        return this.data.remove();
    }

    @Override
    public T peek() {
        return this.data.getValueByIndex();
    }

    @Override
    public int getSize() {
        return this.data.getSize();
    }

    @Override
    public boolean isEmpty() {
        return this.data.isEmpty();
    }
}

4.循环队列的复杂度分析

三、栈和队列的互相实现

既然我们了解了栈和队列,知道了这两种数据结构十分相似,也就可以大胆假设以下,可不可以相互实现,不是用上面所写的以数组为底层,而是相互为底层存储。

1.用栈来实现队列

import java.util.Stack;

class MyQueue {
    private Stack<Integer> A;
    private Stack<Integer> B;

    public MyQueue() {
        A = new Stack<>();
        B = new Stack<>();
    }

    public void push(int x) {
        while (!B.isEmpty()) {
            A.push(B.pop());
        }
        A.push(x);
        while (!A.isEmpty()) {
            B.push(A.pop());
        }
    }

    public int pop() {
        return B.pop();
    }

    public int peek() {
        return B.peek();
    }

    public boolean empty() {
        return B.isEmpty();
    }
}

2.用队列实现栈

import java.util.LinkedList;
import java.util.Queue;

class MyStack {
    private Queue<Integer> queue1;
    private Queue<Integer> queue2;

    public MyStack() {
        queue1 = new LinkedList<>();
        queue2 = new LinkedList<>();
    }

    public void push(int x) {
        queue2.add(x);
        while (!queue1.isEmpty()) {
            queue2.add(queue1.remove());
        }
        Queue<Integer> temp = queue1;
        queue1 = queue2;
        queue2 = temp;
    }

    public int pop() {
        return queue1.remove();
    }

    public int top() {
        return queue1.peek();
    }

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

这就是这两种数据结构相互实现的代码

在LeetCode中也有相对应的题目:

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台(栈实现队列)

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台(队列实现栈)

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

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

相关文章

win系统环境搭建(十二)——Windows系统下使用docker安装redis

windows环境搭建专栏&#x1f517;点击跳转 win系统环境搭建&#xff08;十二&#xff09;——Windows系统下使用docker安装redis 文章目录 win系统环境搭建&#xff08;十二&#xff09;——Windows系统下使用docker安装redis1.创建文件夹2.docker-compose.yaml配置文件3.red…

《WebKit 技术内幕》之四(1): 资源加载和网络栈

第四章 资源加载和网络栈 使用网络栈来下载网页和网页资源是渲染引擎工作的第一步 1.WebKit 资源加载机制 1.1 资源 网页本身就是一种资源、网页还需要依赖很多其他的资源(图片、视频) &#xff08;1&#xff09;HTML 支持的资源主要包括以下几种类型&#xff1a; HTML 页…

【动态规划】【C++算法】741摘樱桃

作者推荐 【动态规划】【数学】【C算法】18赛车 涉及知识点 动态规划 LeetCode741 摘樱桃 给你一个 n x n 的网格 grid &#xff0c;代表一块樱桃地&#xff0c;每个格子由以下三种数字的一种来表示&#xff1a; 0 表示这个格子是空的&#xff0c;所以你可以穿过它。 1 表…

Golang 搭建 WebSocket 应用(六) - 监控

我在上一篇文章中&#xff0c;提到了目前的认证方式存在一些问题&#xff0c;需要替换为一种更简单的认证方式。 但是最后发现&#xff0c;认证这个实在是没有办法简单化&#xff0c;认证本身又是另外一个不小的话题了&#xff0c;因此关于这一点先留个坑。 本文先讨论一下另外…

前端开发必备 HTML的常用标签(二)

目录 一、HTML语言 二、水平线标签 三、字体样式标签 四、注释和特殊符号 一、HTML语言 HTML&#xff08;Hypertext Markup Language&#xff09;是一种标记语言&#xff0c;用于创建网页的结构和内容。它由一系列的标签组成&#xff0c;这些标签定义了网页中各个元素的结…

商铺工厂119消防火灾SOS声光一键报警器平台联网

商铺工厂119消防火灾SOS声光一键报警器平台联网 1.设有火灾自动报警系统的建筑&#xff0c;宜选择符合相关现行国家技术标准的消防应急广播、火灾声光警报类产品&#xff0c;由火灾报警或消防联动控制器进行控制&#xff0c;在消防控制室应能一键启动全楼火灾声光警报或向全楼进…

阿里云腾讯七牛内容安全配置

一&#xff0c;阿里云 1&#xff0c;配置RAM角色权限 向RAM用户授权系统策略权限&#xff1a;AliyunYundunGreenWebFullAccess 2&#xff0c;内容安全控制台——授权访问OSS 不授权——会报错——no permission(not authorized about role AliyunCIPScanOSSRole)

Pytest插件“pytest-selenium” - 让自动化测试更简洁

在现代Web应用的开发中,自动化测试成为确保网站质量的重要手段之一。而Pytest插件 pytest-selenium 则为开发者提供了简单而强大的工具,以便于使用Python进行Web应用的自动化测试。本文将深入介绍 pytest-selenium 插件的基本用法和实际案例,助你轻松进入无忧的Web应用测试之…

LeetCode 9.回文数(python版)

需求 给你一个整数 x &#xff0c;如果 x 是一个回文整数&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。回文数是指正序&#xff08;从左向右&#xff09;和倒序&#xff08;从右向左&#xff09;读都是一样的整数。 例如&#xff0c;121 是回文&#xff0…

【惠友小课堂】正确认识「股骨头坏死」,必读!

在上一篇门诊故事中讲到的孙女士&#xff0c;一开始觉得自己腿疼的原因可能是股骨头坏死&#xff0c;结果在王教授的诊断下发现其实是髋关节发育不良&#xff0c;给出的专业建议是需要进行髋关节置换手术治疗。这恰恰反映了一个情况&#xff0c;很多病人会把“腿疼”的原因归咎…

【GitHub项目推荐--微软开源的可视化工具】【转载】

说到数据可视化&#xff0c;大家都很熟悉了&#xff0c;设计师、数据分析师、数据科学家等&#xff0c;都需要用各种方式各种途径做着数据可视化的工作.....当然许多程序员在工作中有时也需要用到一些数据可视化工具&#xff0c;如果工具用得好&#xff0c;就可以把原本枯燥凌乱…

中国电子学会2021年12月份青少年软件编程Scratch图形化等级考试试卷一级真题(含答案)

一、单选题&#xff08;共25题&#xff0c;每题2分&#xff0c;共50分&#xff09; 1.点击下列哪个按钮&#xff0c;可以让正在运行的程序停下来&#xff1f;&#xff08;&#xff09;(2分) A. B. C. D. 2.小乔完成了一个编程作品后&#xff0c;点击“文件”中的“保…

【Linux】Linux基本操作(二):rm rmdir man cp mv cat echo

承接上文&#xff1a; 【【Linux】Linux基本操作&#xff08;一&#xff09;&#xff1a;初识操作系统、ls、cd、touch、mkdir、pwd 】 目录 1.rmdir指令 && rm 指令&#xff1a; rmdir -p #当子目录被删除后如果父目录也变成空目录的话&#xff0c;就连带父目录一…

【设计模式】文件目录管理是组合模式吗?

组合模式是什么&#xff1f; 组合模式是一种将对象组合成树形结构以表示"部分-整体"的层次结构的设计模式。它使得用户对单个对象和组合对象的使用具有一致性。 组合模式在什么情况下使用&#xff1f; 当你发现你需要在代码中实现树形数据结构&#xff0c;让整体-部…

户外机器人区域覆盖算法仿真测试平台设计与实现(预告)

要求14周完成。一定要熟练掌握人工智能工具的使用。 起伏地形环境多机器人编队运动控制与路径规划研究_2016年中小结-CSDN博客 简要版本 随着机器人技术的快速发展&#xff0c;户外机器人在农业、环境监测、搜索与救援等领域的应用日益广泛。为了实现高效、准确的区域覆盖&…

基于docker创建nginx容器

docker一键安装可以参考我这个博客&#xff1a;一键安装docker 1.创建基础容器 docker run -p280:280 --name nginx -d nginx创建挂载到容器的宿主机文件夹 mkdir -p /home/000nginx-ebrms-ftp/html mkdir -p /home/000nginx-ebrms-ftp/logs mkdir -p /home/000nginx-ebrms-f…

FPGA高端项目:Xilinx Artix7 系列FPGA纯verilog图像缩放工程解决方案 提供4套工程源码和技术支持

目录 1、前言版本更新说明给读者的一封信FPGA就业高端项目培训计划免责声明 2、相关方案推荐我这里已有的FPGA图像缩放方案本方案在Xilinx Kintex7 系列FPGA上的应用本方案在国产FPGA紫光同创系列上的应用本方案在国产FPGA高云系列上的应用 3、设计思路框架设计框图视频源选择o…

vue中引入sass、scss

常规步骤 1. 创建项目 使用vue cli 脚手架工具创建项目 vue create xxxx2. 创建全局样式文件 全局样式变量 路径&#xff1a;/assets/styles/variables.scss //flex 布局变量 $--flex-direction: ("row", "column"); $--flex-position: ("start"…

如何从命令行运行testng.xml?

目录 创建一个新的java项目并从命令行运行testng.xml 使用命令行运行XML文件 从命令行运行现有maven项目的XML文件 在这篇文章中&#xff0c;我们将使用命令行运行testng.xml。有多种场景需要使用命令行工具运行testng.xml。也许您已经创建了一个maven项目&#xff0c;现在想…

2024执业医师考试报名流程及上传照片要求详解

2024年执业医师和助理医师考试的报名工作将于1月22日正式启动&#xff0c;报名截止日期为2月4日。建议考生尽早报名&#xff0c;以避免在报名截止日期临近时出现拥挤情况。您可根据本文介绍&#xff0c;提前准备好报名所需资料、证件照电子版和相关证明材料&#xff0c;并了解报…