我理解的数据结构(三)—— 队列(Queue)

一、队列

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

二、数组队列与循环队列

1. 数组队列

如果你有看过我之前的文章不要小看了数组或者,你就会发现,自己封装一个数组队列是如此的轻松加愉快!

(1)先定义一个接口,接口中定义队列需要实现的方法

```
public interface Queue<E> {
int getSize();
boolean isEmpty();
// 查看队首元素
E getFront();
// 入队
void enqueue(E ele);
// 出队
E dequeue();
}
```

(2)实现数组队列

```
public class ArrayQueue<E> implements Queue<E> {

// 这里的数组是在之前的文章中封装好的,直接拿来用就好了
private ArrayNew&lt;E&gt; array; public ArrayQueue(int capacity) {
array = new ArrayNew&lt;&gt;(capacity);
} public ArrayQueue() {
this(10);
} public int getCapacity() {
return array.getCapacity();
} @Override
public int getSize() {
return array.getSize();
} @Override
public boolean isEmpty() {
return array.isEmpty();
} @Override
public E getFront() {
return array.getFirst();
} @Override
public void enqueue(E ele) {
array.addLast(ele);
} @Override
public E dequeue() {
return array.removeFirst();
} @Override
public String toString() { StringBuffer res = new StringBuffer(); res.append(String.format("arrayQueue: size = %d, capacity = %d\n", getSize(), getCapacity()));
res.append("front ["); for (int i = 0; i &lt; array.getSize(); i++) {
res.append(array.get(i));
if (i != getSize() - 1) {
res.append(", ");
}
}
res.append("] tail");
return res.toString(); }

}


<p><strong>(3)数组队列的复杂度</strong></p>
<table>
<thead><tr>
<th align="center">方法</th>
<th align="center">复杂度</th>
</tr></thead>
<tbody>
<tr>
<td align="center"><code>enqueue</code></td>
<td align="center">O(1) 均摊</td>
</tr>
<tr>
<td align="center"><code>dequeue</code></td>
<td align="center">O(n)</td>
</tr>
<tr>
<td align="center"><code>front</code></td>
<td align="center">O(1)</td>
</tr>
<tr>
<td align="center"><code>getSize</code></td>
<td align="center">O(1)</td>
</tr>
<tr>
<td align="center"><code>isEmpty</code></td>
<td align="center">O(1)</td>
</tr>
</tbody>
</table>
<blockquote>这个时候我们会发现,在进行出队操作的时候,数组队列的复杂度是0(n),如果我们频繁的进行出队操作,那么其实数组队列的效率是很低的,如何提升数组队列的性能呢?这个时候我们就要用到循环队列了。</blockquote>
<h4>2. 循环队列队列</h4>
<blockquote>循环队列的原理:</blockquote>
<ol>
<li>
<code>dequeue</code>时,不要在去除队首元素时,把整体向前移动</li>
<li>维护 <code>front</code> 、 <code>tail</code> 和 <code>size</code> 这三个属性</li>
<li>
<code>enqueue</code>的时候<code>tail++</code>
</li>
<li>
<code>dequeue</code>的时候<code>front++</code>
</li>
</ol> ![](https://img2018.cnblogs.com/blog/1504257/201811/1504257-20181117135616157-1981589685.png) <p><strong>(1)实现循环队列</strong></p>

public class LoopQueue<E> implements Queue<E> {

private E[] array;
private int size;
private int front;
private int tail; public LoopQueue(int capacity) {
// 我们需要浪费一个空间去判断队列是否已满,所以需要把capacity + 1
array = (E[])new Object[capacity + 1];
front = 0;
tail = 0;
size = 0;
} public LoopQueue() {
this(10);
} // 返回用户传递的队列大小
public int getCapacity() {
return array.length - 1;
} @Override
public int getSize() {
return size;
} @Override
public boolean isEmpty() {
return front == tail;
} @Override
public E getFront() {
if (isEmpty()) {
throw new IllegalArgumentException("Queue is empty. Can't get front.");
} return array[0];
} @Override
public void enqueue(E ele) { if (front == (tail + 1) % array.length) {
// 扩展队列长度为原长度2倍
resize(getCapacity() * 2);
} array[tail] = ele;
size++;
tail = (tail + 1) % array.length;
} @Override
public E dequeue() { if (isEmpty()) { // 队列为空
throw new IllegalArgumentException("Queue is empty. Can't get dequeue.");
} E ele = array[front]; size--;
array[front] = null;
front = (front + 1) % array.length; if (size == getCapacity() / 4 &amp;&amp; getCapacity() / 2 != 0) {
resize(getCapacity() / 2);
} return ele; } private void resize(int newCapacity) {
E[] newArray = (E[]) new Object[newCapacity + 1]; for (int i = 0; i &lt; size; i++) {
newArray[i] = array[(front + i) % array.length];
} array = newArray;
front = 0;
tail = size;
} @Override
public String toString() {
StringBuffer res = new StringBuffer(); res.append(String.format("queue: size = %d, capacity = %d\n", getSize(), getCapacity()));
res.append("front ["); // 循环条件,和循环增量都要注意下
for (int i = front; i != tail; i = (i + 1) % array.length) {
res.append(array[i]); if ((i + 1) % array.length != tail) {
res.append(", ");
}
}
res.append("] tail"); return res.toString();
}

}


<p><strong>(2)循环队列的复杂度</strong></p>
<table>
<thead><tr>
<th align="center">方法</th>
<th align="center">复杂度</th>
</tr></thead>
<tbody>
<tr>
<td align="center"><code>enqueue</code></td>
<td align="center">O(1) 均摊</td>
</tr>
<tr>
<td align="center"><code>dequeue</code></td>
<td align="center">O(1) 均摊</td>
</tr>
<tr>
<td align="center"><code>front</code></td>
<td align="center">O(1)</td>
</tr>
<tr>
<td align="center"><code>getSize</code></td>
<td align="center">O(1)</td>
</tr>
<tr>
<td align="center"><code>isEmpty</code></td>
<td align="center">O(1)</td>
</tr>
</tbody>
</table>
<h3>三、用时间说话</h3>
<p><strong>(1)用时方法</strong></p>

public static double test(Queue<Integer> q, int opCount) {

// 纳秒
long startTime = System.nanoTime(); Random random = new Random(); for (int i = 0; i &lt; opCount; i++) {
q.enqueue(random.nextInt(Integer.MAX_VALUE));
}
for (int i = 0; i &lt; opCount; i++) {
q.dequeue();
} // 纳秒
long endTime = System.nanoTime(); return (endTime - startTime) / 1000000000.0;

}


<p><strong>(2)调用</strong></p>

// 十万次入队和十万次出队操作

int opCount = 100000;

ArrayQueue<Integer> aq = new ArrayQueue<>();

double time1 = test(aq, opCount);

System.out.println(time1);

LoopQueue<Integer> lq = new LoopQueue<>();

double time2 = test(lq, opCount);

System.out.println(time2);


<p><strong>(3)结果</strong></p>
<ul>
<li>14.635995113</li>
<li>0.054536447</li>
</ul>
<blockquote>这个就是算法和数据结构的力量!</blockquote> 原文地址:https://segmentfault.com/a/1190000016147024

我理解的数据结构(三)—— 队列(Queue)的更多相关文章

  1. Python与数据结构[2] -> 队列/Queue[0] -> 数组队列的 Python 实现

    队列 / Queue 数组队列 数组队列是队列基于数组的一种实现,其实现类似于数组栈,是一种FIFO的线性数据结构. Queue: <--| 1 | 2 | 3 | 4 | 5 |<-- ...

  2. 数据结构:队列queue 函数push() pop size empty front back

    队列queue: push() pop() size() empty() front() back() push()  队列中由于是先进先出,push即在队尾插入一个元素,如:可以输出:Hello W ...

  3. 算法与数据结构基础 - 队列(Queue)

    队列基础 队列具有“先进先出”的特点,用这个特点我们可以用它来处理时间序列相关或先后次序相关的问题,例如 LeetCode题目 933. Number of Recent Calls,时间复杂度O(1 ...

  4. 数据结构之队列(queue)

    队列介绍 1.队列是一个有序列表,可以用数组或是链表来实现. 2.遵循先入先出的原则.即:先存入队列的数据,要先取出.后存入的要后取出. 应用场景 比如某某银行叫号系统: 数组模拟队列 队列本身是有序 ...

  5. Python进阶----异步同步,阻塞非阻塞,线程池(进程池)的异步+回调机制实行并发, 线程队列(Queue, LifoQueue,PriorityQueue), 事件Event,线程的三个状态(就绪,挂起,运行) ,***协程概念,yield模拟并发(有缺陷),Greenlet模块(手动切换),Gevent(协程并发)

    Python进阶----异步同步,阻塞非阻塞,线程池(进程池)的异步+回调机制实行并发, 线程队列(Queue, LifoQueue,PriorityQueue), 事件Event,线程的三个状态(就 ...

  6. Java 集合深入理解(9):Queue 队列

    点击查看 Java 集合框架深入理解 系列, - ( ゜- ゜)つロ 乾杯~ 今天心情不太好,来学一下 List 吧! 什么是队列 队列是数据结构中比较重要的一种类型,它支持 FIFO,尾部添加.头部 ...

  7. 【Java数据结构学习笔记之二】Java数据结构与算法之队列(Queue)实现

      本篇是数据结构与算法的第三篇,本篇我们将来了解一下知识点: 队列的抽象数据类型 顺序队列的设计与实现 链式队列的设计与实现 队列应用的简单举例 优先队列的设置与实现双链表实现 队列的抽象数据类型 ...

  8. 【Java数据结构学习笔记之三】Java数据结构与算法之队列(Queue)实现

      本篇是数据结构与算法的第三篇,本篇我们将来了解一下知识点: 队列的抽象数据类型 顺序队列的设计与实现 链式队列的设计与实现 队列应用的简单举例 优先队列的设置与实现双链表实现 队列的抽象数据类型 ...

  9. 数据结构——链队列(linked queue)

    /* linkedQueue.c */ /* 链队列 */ #include <stdio.h> #include <stdlib.h> #include <stdboo ...

随机推荐

  1. Linux/CentOS各种服务框架的搭建完整流程

    在2012年的时候,由于要照应新人对Linux以及相关服务的了解和学习,我特地把当时我们创业项目的全部服务搭建过程写成了一篇文档,能够让他们学习而且有所參照. 以下就以这篇文档为底稿,进行一些改动和敏 ...

  2. buaa 1033 Easy Problem(三分)(简单)

    Easy Problem 时间限制:1000 ms  |  内存限制:65536 KB 描写叙述 In this problem, you're to calculate the distance b ...

  3. 一句话实现Mysql查询结果带行号

    SELECT @rowno:=@rowno + 1 AS rowno,a.* FROM tableName a,(SELECT @rowno:=0) b

  4. Java压缩技术(一) ZLib

    原文:http://snowolf.iteye.com/blog/465433 有关ZLib可参见官方主页 http://www.zlib.net/ ZLib可以简单的理解为压缩/解压缩算法,它与ZI ...

  5. ZOJ2477 Magic Cube

    题目: This is a very popular game for children. In this game, there's a cube, which consists of 3 * 3 ...

  6. css 画箭头

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...

  7. vmware 14黑屏处理办法

    从12升级到了14,但是发现所有的虚拟机都不能用了,黑屏.挂起的时候反而会显示界面,但是继续运行就是黑屏. 记录下解决办法. 修复LSP 以管理员身份运行CMD命令: netsh winsock re ...

  8. 汇编程序10:计算长度为C字节的数据和

    assume cs:code code segment mov ax,0ffffh //起始段地址 mov ds,ax mov bx,0 //偏移变量 mov dx,0 //保存结果 mov cx,1 ...

  9. golang单点推送

    package main import ( "encoding/json" "flag" "fmt" "log" &qu ...

  10. itext 生成doc文档 小结(自己备忘)

    1.引入maven <dependency> <groupId>com.lowagie</groupId> <artifactId>itext</ ...