当前位置: 首页 > news >正文

数据结构基础之栈和队列

目录​​​​​​​

前言

1、栈

 2、队列

2.1、实现队列

2.2、循环队列


前言

上一篇中我们介绍了数据结构基础中的《动态数组》,本篇我们继续来学习两种基本的数据结构——栈和队列。

1、栈

特点:栈也是一种线性结构,相比数组,栈对应的操作是数组的子集,只能从一端添加元素,也只能从同一端取出元素,这一端称为栈顶。栈是一种后进先出的数据结构,即Last In First Out(LIFO)。

上面说到栈对应的操作是数组的子集,因此我们就基于上一篇中实现的动态数组来快速的实现一个栈。

首先定义一个接口,定义相关功能方法:

然后让栈来实现接口中的具体功能:

import arr.Array;public class ArrayStack<E> implements Stack<E> {Array<E> array;public ArrayStack(int capacity) {array = new Array<>(capacity);}public ArrayStack() {array = new Array<>();}public int getCapacity() {return array.getCapacity();}@Overridepublic int getSize() {return array.getSize();}@Overridepublic boolean isEmpty() {return array.isEmpty();}@Overridepublic void push(E e) {array.addLast(e);}@Overridepublic E pop() {return array.removeLast();}@Overridepublic E peek() {return array.getLast();}@Overridepublic String toString() {StringBuilder res = new StringBuilder();res.append("Stack").append("[");for (int i = 0; i < array.getSize(); i++) {res.append(array.get(i));if (i != array.getSize() - 1) {res.append(",");}}res.append("] Top");return res.toString();}
}

写一个测试方法:

执行结果如下:

 2、队列

2.1、实现队列

队列也是一种线性结构,相比数组,队列对应的操作也是数组的子集,队列只能从一端(队尾)添加元素,只能从另一端(队首)取出元素。队列是一种先进先出的数据结构(先到先得),即:First In First Out(FIFO)。

由于队列对应的操作同样是数组的子集,那么我们让然也是基于上一篇中实现的动态数组来快速的实现一个栈。 

定义一个接口,定义相关功能方法:

然后让队列来实现接口中的具体功能:

import arr.Array;public class ArrayQueue<E> implements Queue<E> {private Array<E> array;public ArrayQueue(int capacity) {array = new Array<>(capacity);}public ArrayQueue(){array = new Array<>();}public int getCapacity(){return array.getCapacity();}@Overridepublic int getSize() {return array.getSize();}@Overridepublic boolean isEmpty() {return array.isEmpty();}@Overridepublic void enqueue(E e) {array.addLast(e);}@Overridepublic E dequeue() {return array.removeFirst();}@Overridepublic E getFront() {return array.getFirst();}@Overridepublic String toString() {StringBuilder res = new StringBuilder();res.append("Queue:").append("Front [");for (int i = 0; i < array.getSize(); i++) {res.append(array.get(i));if (i != array.getSize() - 1) {res.append(",");}}res.append("] tail");return res.toString();}
}

同样的写一个测试类:

 

执行结果如下:

2.2、循环队列

初始时front和tail都是指向下标为0的位置,当有元素入队时,tail指向该元素的下一个位置((tail+1)%capacity),元素出队时,front向后移动一个位置,因此,循环队列有元素出队时,无需让所有的元素都移动一个位置,只需让front的指向移动一次即可,示意图如下:

  ​​​​​​​

下面我们来通过代码看一下循环队列该怎么实现:

public class LoopQueue<E> implements Queue<E> {private E[] data;private int front, tail;private int size;public LoopQueue(int capacity) {data = (E[]) new Object[capacity + 1];front = 0;tail = 0;size = 0;}public LoopQueue() {this(10);}public int getCapacity() {return data.length - 1;}@Overridepublic int getSize() {return size;}@Overridepublic boolean isEmpty() {return front == tail;}@Overridepublic void enqueue(E e) {if ((tail + 1) % data.length == front) {resize(getCapacity() * 2);}data[tail] = e;tail = (tail + 1) % data.length;size++;}private void resize(int newCapacity) {E[] newdata = (E[]) new Object[newCapacity + 1];for (int i = 0; i < size; i++) {newdata[i] = data[(i + front) % data.length];}data = newdata;front = 0;tail = size;}@Overridepublic E dequeue() {if (isEmpty()) {throw new IllegalArgumentException("队列为空");}E ret = data[front];data[front] = null;front = (front + 1) % data.length;size--;if (size == getCapacity() / 4 && getCapacity() / 2 != 0) {resize(getCapacity() / 2);}return null;}@Overridepublic E getFront() {if (isEmpty()) {throw new IllegalArgumentException("队列为空");}return data[front];}@Overridepublic String toString() {StringBuilder res = new StringBuilder();res.append(String.format("Queue: size=%d,capacity=%d\n", size, getCapacity())).append("front [");for (int i = front; i != tail; i = (i + 1) % data.length) {res.append(data[i]);if ((i+1)%data.length != tail) {res.append(",");}}res.append("] tail");return res.toString();}
}

同样的测试程序:

执行结果如下:

好了,关于栈和队列的内容就说这么多吧,咱们下期再会!

祝:工作顺利!

http://www.lryc.cn/news/21808.html

相关文章:

  • 【Spark分布式内存计算框架——Spark Streaming】3.入门案例(上)官方案例运行
  • 【博学谷学习记录】超强总结,用心分享 | 架构师 Tomcat源码学习总结
  • 泛型<E>
  • 你对MANIFEST.MF这个文件知道多少?
  • 史上最经典垃圾回收器(CMS,G1)详解、适用场景及特点、使用命令
  • Hive查询中的优化
  • 【开发规范】go项目开发中的[流程,git,代码,目录,微服务仓库管理,静态检查]
  • 数组初始化方式与decimal.InvalidOperation
  • 【Opencv-python】之入门安装
  • MySQL进阶(二)
  • 热爱所有热爱
  • Redis学习之数据删除与淘汰策略(七)
  • HashMap 面试专题
  • 域组策略自动更新实验报告
  • Java自定义生成二维码(兼容你所有的需求)
  • Spring事务的隔离级别
  • JVM系统优化实践(4):以支付系统为例
  • 16- TensorFlow实现线性回归和逻辑回归 (TensorFlow系列) (深度学习)
  • 无自动化测试系统设计方法论
  • 架构初探-学习笔记
  • 在成都想转行IT,选择什么专业比较好?
  • 【Spark分布式内存计算框架——Spark Streaming】4.入门案例(下)Streaming 工作原理
  • 2、算法先导---思维能力与工具
  • WordPress 函数:add_theme_support() 开启主题自定义功能(全面)
  • Winform控件开发(16)——Timer(史上最全)
  • 游戏高度可配置化:通用数据引擎(data-e)及其在模块化游戏开发中的应用构想图解
  • CountDownLatch与CyclicBarrier原理剖析
  • NLP中的对话机器人——预训练基准模型
  • C语言学习及复习笔记-【14】C文件读写
  • 模拟退火算法优化灰色