【数据结构与算法】(5)基础数据结构之队列 链表实现、环形数组实现详细代码示例讲解

目录

    • 2.4 队列
      • 1) 概述
      • 2) 链表实现
      • 3) 环形数组实现

在这里插入图片描述

2.4 队列

1) 概述

计算机科学中,queue 是以顺序的方式维护的一组数据集合,在一端添加数据,从另一端移除数据。习惯来说,添加的一端称为,移除的一端称为,就如同生活中的排队买商品

In computer science, a queue is a collection of entities that are maintained in a sequence and can be modified by the addition of entities at one end of the sequence and the removal of entities from the other end of the sequence

先定义一个简化的队列接口

public interface Queue<E> {/*** 向队列尾插入值* @param value 待插入值* @return 插入成功返回 true, 插入失败返回 false*/boolean offer(E value);/*** 从对列头获取值, 并移除* @return 如果队列非空返回对头值, 否则返回 null*/E poll();/*** 从对列头获取值, 不移除* @return 如果队列非空返回对头值, 否则返回 null*/E peek();/*** 检查队列是否为空* @return 空返回 true, 否则返回 false*/boolean isEmpty();/*** 检查队列是否已满* @return 满返回 true, 否则返回 false*/boolean isFull();
}

2) 链表实现

下面以单向环形带哨兵链表方式来实现队列

在这里插入图片描述

代码

public class LinkedListQueue<E>implements Queue<E>, Iterable<E> {private static class Node<E> {E value;Node<E> next;public Node(E value, Node<E> next) {this.value = value;this.next = next;}}private Node<E> head = new Node<>(null, null);private Node<E> tail = head;private int size = 0;private int capacity = Integer.MAX_VALUE;{tail.next = head;}public LinkedListQueue() {}public LinkedListQueue(int capacity) {this.capacity = capacity;}@Overridepublic boolean offer(E value) {if (isFull()) {return false;}Node<E> added = new Node<>(value, head);tail.next = added;tail = added;size++;return true;}@Overridepublic E poll() {if (isEmpty()) {return null;}Node<E> first = head.next;head.next = first.next;if (first == tail) {tail = head;}size--;return first.value;}@Overridepublic E peek() {if (isEmpty()) {return null;}return head.next.value;}@Overridepublic boolean isEmpty() {return head == tail;}@Overridepublic boolean isFull() {return size == capacity;}@Overridepublic Iterator<E> iterator() {return new Iterator<E>() {Node<E> p = head.next;@Overridepublic boolean hasNext() {return p != head;}@Overridepublic E next() {E value = p.value;p = p.next;return value;}};}
}

3) 环形数组实现

好处

  1. 对比普通数组,起点和终点更为自由,不用考虑数据移动
  2. “环”意味着不会存在【越界】问题
  3. 数组性能更佳
  4. 环形数组比较适合实现有界队列、RingBuffer 等

在这里插入图片描述

下标计算

例如,数组长度是 5,当前位置是 3 ,向前走 2 步,此时下标为 ( 3 + 2 ) % 5 = 0 (3 + 2)\%5 = 0 (3+2)%5=0

在这里插入图片描述

( c u r + s t e p ) % l e n g t h (cur + step) \% length (cur+step)%length

  • cur 当前指针位置
  • step 前进步数
  • length 数组长度

注意:

  • 如果 step = 1,也就是一次走一步,可以在 >= length 时重置为 0 即可

判断空

在这里插入图片描述

判断满

在这里插入图片描述

满之后的策略可以根据业务需求决定

  • 例如我们要实现的环形队列,满之后就拒绝入队

代码

public class ArrayQueue<E> implements Queue<E>, Iterable<E>{private int head = 0;private int tail = 0;private final E[] array;private final int length;@SuppressWarnings("all")public ArrayQueue(int capacity) {length = capacity + 1;array = (E[]) new Object[length];}@Overridepublic boolean offer(E value) {if (isFull()) {return false;}array[tail] = value;tail = (tail + 1) % length;return true;}@Overridepublic E poll() {if (isEmpty()) {return null;}E value = array[head];head = (head + 1) % length;return value;}@Overridepublic E peek() {if (isEmpty()) {return null;}return array[head];}@Overridepublic boolean isEmpty() {return tail == head;}@Overridepublic boolean isFull() {return (tail + 1) % length == head;}@Overridepublic Iterator<E> iterator() {return new Iterator<E>() {int p = head;@Overridepublic boolean hasNext() {return p != tail;}@Overridepublic E next() {E value = array[p];p = (p + 1) % array.length;return value;}};}
}

判断空、满方法2

引入 size

public class ArrayQueue2<E> implements Queue<E>, Iterable<E> {private int head = 0;private int tail = 0;private final E[] array;private final int capacity;private int size = 0;@SuppressWarnings("all")public ArrayQueue2(int capacity) {this.capacity = capacity;array = (E[]) new Object[capacity];}@Overridepublic boolean offer(E value) {if (isFull()) {return false;}array[tail] = value;tail = (tail + 1) % capacity;size++;return true;}@Overridepublic E poll() {if (isEmpty()) {return null;}E value = array[head];head = (head + 1) % capacity;size--;return value;}@Overridepublic E peek() {if (isEmpty()) {return null;}return array[head];}@Overridepublic boolean isEmpty() {return size == 0;}@Overridepublic boolean isFull() {return size == capacity;}@Overridepublic Iterator<E> iterator() {return new Iterator<E>() {int p = head;@Overridepublic boolean hasNext() {return p != tail;}@Overridepublic E next() {E value = array[p];p = (p + 1) % capacity;return value;}};}
}

判断空、满方法3

  • head 和 tail 不断递增,用到索引时,再用它们进行计算,两个问题

    • 如何保证 head 和 tail 自增超过正整数最大值的正确性

    • 如何让取模运算性能更高

  • 答案:让 capacity 为 2 的幂

public class ArrayQueue3<E> implements Queue<E>, Iterable<E> {private int head = 0;private int tail = 0;private final E[] array;private final int capacity;@SuppressWarnings("all")public ArrayQueue3(int capacity) {if ((capacity & capacity - 1) != 0) {throw new IllegalArgumentException("capacity 必须为 2 的幂");}this.capacity = capacity;array = (E[]) new Object[this.capacity];}@Overridepublic boolean offer(E value) {if (isFull()) {return false;}array[tail & capacity - 1] = value;tail++;return true;}@Overridepublic E poll() {if (isEmpty()) {return null;}E value = array[head & capacity - 1];head++;return value;}@Overridepublic E peek() {if (isEmpty()) {return null;}return array[head & capacity - 1];}@Overridepublic boolean isEmpty() {return tail - head == 0;}@Overridepublic boolean isFull() {return tail - head == capacity;}@Overridepublic Iterator<E> iterator() {return new Iterator<E>() {int p = head;@Overridepublic boolean hasNext() {return p != tail;}@Overridepublic E next() {E value = array[p & capacity - 1];p++;return value;}};}
}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

保姆级系列:各种打印机驱动的安装和使用

保姆级系列&#xff1a;各种打印机驱动的安装和使用 1.介绍2.下载3.安装4.实践教程5.总结 1.介绍 市面上打印机品牌和型号众多&#xff0c;打印机接口目前主要分为如下几种&#xff1a; 逻辑端口&#xff1a;TCP/IP、WSD、USB、LPT、COM 物理端口&#xff1a;RJ45、DB15母、US…

BFS——双向广搜+A—star

有时候从一个点能扩展出来的情况很多&#xff0c;这样几层之后搜索空间就很大了&#xff0c;我们采用从两端同时进行搜索的策略&#xff0c;压缩搜索空间。 190. 字串变换(190. 字串变换 - AcWing题库) 思路&#xff1a;这题因为变化规则很多&#xff0c;所以我们一层一层往外…

19113133262(微信同号)2024年光电信息与机器视觉国际学术会议(ICOIMV 2024)

【征稿进行时|见刊、检索快速稳定】2024年光电信息与机器视觉国际学术会议(ICOIMV 2024) 2024 International Conference Optoelectronic Information and Machine Vision(ICOIMV 2024) 一、【会议简介】 本次会议的主题为“光电信息与机器视觉的未来发展”。围绕这一主题&…

06 - python操作xml

认识XML 与HTML很像&#xff0c;是一种将数据存储在标记之间的标记语言&#xff0c;用户可以自定义自己的标记。 XML文件可以表示称为&#xff1a;XML树。这个XML树从根元素开始&#xff0c;根元素进一步分支到子元素。XML文件的每个元素都是XML树的一个节点&#xff0c;没有…

kafka-splunk数据通路实践

目的&#xff1a; 鉴于目前网络上没有完整的kafka数据投递至splunk教程&#xff0c;通过本文操作步骤&#xff0c;您将实现kafka数据投递至splunk日志系统 实现思路&#xff1a; 创建kafka集群部署splunk&#xff0c;设置HTTP事件收集器部署connector服务创建connector任务&a…

Linux文件编译

目录 一、GCC编译 1.直接编译 2.分步编译 预处理&#xff1a; 编译&#xff1a; 汇编&#xff1a; 链接&#xff1a; 3.多文件编译 4.G 二、Make 1.概述 2.使用步骤 3.makefile创建规则 3.1一个基本规则 3.2两个常用函数 4.示例文件 三、GDB 示例&#xff1a;…

优量汇的广告填充率有多高?

一些量级小的媒体在广告变现初期&#xff0c;以接入广告联盟为主&#xff0c; 广告填充率是衡量广告平台表现和广告变现效率的重要指标。 当用户打开APP时&#xff0c;开发者收到一个对应的广告请求。这个广告请求可以被填充或不被填充&#xff0c;广告填充率广告填充数/广告请…

代码随想录算法训练营第27天| Leetcode 39. 组合总和、40.组合总和II、131.分割回文串

目录 Leetcode 39. 组合总和 Leetcode 40.组合总和II Leetcode 131.分割回文串 Leetcode 39. 组合总和 题目链接&#xff1a;Leetcode 39. 组合总和 题目描述&#xff1a;给定一个无重复元素的数组 candidates 和一个目标数 target &#xff0c;找出 candidates 中所有可以使…

070:vue+cesium: 利用canvas设置径向渐变色材质

相关API参考: https://cesium.com/learn/cesiumjs/ref-doc/ColorMaterialProperty.html 第070个 点击查看专栏目录 本示例的目的是介绍如何在vue+cesium中设置线性渐变色的材质,这里使用canvas的辅助方法。 直接复制下面的 vue+cesium源代码,操作2分钟即可运行实现效果. …

uniapp+uView 【详解】录音,自制音频播放器

效果预览 代码实现 <template><view class"btnListBox"><view class"audioBox" v-if"audioLength"><u-row><u-col span"2"><u--text aligncenter :text"currentTime"></u--text>…

android inset 管理

目录 简介 Insets管理架构 Insets相关类图 app侧的类 WMS侧的类 inset show的流程 接口 流程 WMS侧确定InsetsSourceControl的流程 两个问题 窗口显示时不改变现有的inset状态 全屏窗口上的dialog 不显示statusbar问题 View 和 DecorView 设置insets信息 输入法显…

图文并茂讲解Travelling Salesman

题目 思路 一道lca板子题&#xff0c;不会的同学可以先康康 详解最近公共祖先(LCA)-CSDN博客 我们可以发现&#xff0c;商人是从1开始&#xff0c;旅行到第一个城镇&#xff0c;再到第二个&#xff0c;第三个…… 那么我们只需要求出1~第一个城镇的距离&#xff0c;第一个城…