package queue;

 /**
* 队列接口
* @author jzj
*
* @param <E>
*/
public interface Queue<E> {
//入队
public void enqueue(E e); //出队
public E dequeue(); //取队列第一个
public E front(); //队列是否为空
public boolean isEmpty(); //队列大小
public int size();
}
 package queue;

 /**
* 循环队列,使用数组实现
* @author jzj
*/
public class ArrayQueue<E> implements Queue<E> { private Object lock = new Object(); // 队列大小
private int size = 1000; // 队列
private E[] arrStr = (E[]) new Object[size]; // 队列指针
private int head = 0; // 队列尾指针
private int tail = 0; /**
* 入队
* @param o
*/
public void enqueue(E o) {
synchronized (lock) { // 如果队列已满
while ((tail + 1) % size == head) {
try {
System.out.println("队列已满," + Thread.currentThread().getName()
+ " 线程阻塞...");
// 队列满时线程阻塞
lock.wait();//注,这里一定要放在while条件里,因为获取锁后,条件不一定还成立
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 如果队列未满
arrStr[tail] = o;
// 指针下移
tail = (tail + 1) % size;
// 入队后通知消费线程
lock.notifyAll();
}
} /**
* 出队
* @return
*/
public E dequeue() {
synchronized (lock) {
// 如果队列为空
while (head == tail) {
try {
System.out.println("队列为空," + Thread.currentThread().getName()
+ " 线程阻塞...");
// 队列空时线程阻塞
lock.wait();//注,这里一定要放在while条件里,因为获取锁后,条件不一定还成立
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 队列非空
E tempStr = arrStr[head]; arrStr[head] = null;//注,这里出队后释放对象,加快回收,不然大的对象可能造内存泄露
head = (head + 1) % size; // 出队后通知生产者
lock.notifyAll();
return tempStr; }
} //取队列第一个
public E front() {
synchronized (lock) {
// 如果队列为空
while (head == tail) {
try {
System.out.println("队列为空," + Thread.currentThread().getName()
+ " 线程阻塞...");
// 队列空时线程阻塞
lock.wait();//注,这里一定要放在while条件里,因为获取锁后,条件不一定还成立
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 队列非空
return arrStr[head];
}
} //队列是否为空
public boolean isEmpty() {
return head == tail;
} //队列大小
public int size() { return Math.abs(tail - head);
}
}

Jdk1.5已有java.util.Queue接口

使用1.5中并发新特性实现循环队列:来源于 API java.util.concurrent.locks.Condition

 //循环缓冲队列,从队首放,从队尾出。牺牲数组的最后一个元素,用来判断队列是否满
class BoundedBuffer {
final Lock lock = new ReentrantLock();//可重入锁
final Condition notFull = lock.newCondition();//缓冲空条件对象
final Condition notEmpty = lock.newCondition();//缓冲非空条件对象 final Object[] items = new Object[100];//缓冲区
int putptr/*队首*/, takeptr/*队尾*/, count/*可用个数*/; //将元素放入缓冲,供生产线程调用
public void put(Object x) throws InterruptedException {
lock.lock();//获取锁
try {
//注,要将await置于循环中,这也wait道理一样
while (count == items.length)
notFull.await();//缓冲满时等待,且释放锁
items[putptr] = x;
//如果队首指针指向数组最后索引时,重新指向数组第一个元素位置
if (++putptr == items.length)
putptr = 0;
++count;//循环队列中存入的元素个数
notEmpty.signal();//放入元素后通知其它消费线程可以消费了
} finally {
lock.unlock();//释放锁
}
} //从缓冲取出元素,供消费线程调用
public Object take() throws InterruptedException {
lock.lock();
try {
while (count == 0)
notEmpty.await();//如果缓冲空则等待
Object x = items[takeptr];
//如果队尾指针指向数组最后索引时,重新指向数组第一个元素位置
if (++takeptr == items.length)
takeptr = 0;
--count;
notFull.signal();//取出后会有空间,通知生产线程
return x;
} finally {
lock.unlock();
}
}
}
 package queue;

 import java.util.LinkedList;

 /**
* 使用 LinkedList 实现队列
* @author jzj
*
* @param <E>
*/
public class LinkedListQueue<E> implements Queue<E> {
private LinkedList<E> linkedList = new LinkedList<E>(); //入队
public void enqueue(E e) {
linkedList.addLast(e);
} //出队
public E dequeue() {
return linkedList.removeFirst();
} //取队列第一个
public E front() {
return linkedList.getFirst();
} //队列是否为空
public boolean isEmpty() {
return linkedList.isEmpty();
} //队列大小
public int size() {
return linkedList.size();
}
}
 package queue;

 import java.util.NoSuchElementException;

 /**
* 使用 循环双向链 实现队列
*
* @author jzj
*
* @param <E>
*/
public class LinkedQueue<E> implements Queue<E> {
private class Entry {
E element;//数据域
Entry next;//后驱节点
Entry previous;//前驱节点 /**
* @param element 数据域
* @param next 后驱节点
* @param previous 前驱节点
*/
Entry(E element, Entry next, Entry previous) {
this.element = element;
this.next = next;
this.previous = previous;
}
} /*
* 头节点,永远代表头。链中无结节时节点中的前后驱指针域指向自己,当有元素时
* 头节点的前驱指针域previous指向链中最后一个节点,而next指针域指向链中的
* 第一个节点
*/
private Entry header = new Entry(null, null, null); private int size = 0;//链表中节点个数,但不包括头节点header public LinkedQueue() {
//初始化时头的前后驱指针都指向自己
header.next = header.previous = header;
} //入队,在链表中的最后位置加入元素,相当于 LinkedList 的add、addBefore、addLast方法实现
public void enqueue(E e) {
//在双向链后面加入元素
Entry newEntry = new Entry(e, header, header.previous);
//让新元素的前驱节点(新增前链的最后点)的前驱指向新加元素
newEntry.previous.next = newEntry;
//让新元素的后驱节点(header头节点)的前驱指向新加元素
newEntry.next.previous = newEntry;
size++;
} //出队,从链表中的第一个元素开始出队,相当于 LinkedList 的removeFirst方法实现
public E dequeue() {
//要出队(删除)的节点的数据域
E first = header.next.element;
Entry e = header.next;
//要删除的节点为头节点时不能删除
if (e == header) {
throw new NoSuchElementException();
} //将删除节点的前驱节点的next域指针指向删除节点的后驱节点
e.previous.next = e.next;
//将删除节点的后驱节点的previous域指针指向删除节点的前驱节点
e.next.previous = e.previous;
size--;
return first;
} //取队列的第一个元素,相当于 LinkedList 的getFirst方法实现
public E front() {
if (size == 0)
throw new NoSuchElementException(); return header.next.element;
} //队列是否为空
public boolean isEmpty() {
return size == 0;
} //队列大小
public int size() {
return size;
}
}

[数据结构与算法]队列Queue 的多种实现的更多相关文章

  1. Airport Simulation (数据结构与算法 – 队列 / Queue 的应用)

    Airport Simulation 是数据结构与算法教材中用于演示Queue的一个小程序(大多数教师似乎会跳过这个练习).主程序会通过输入总的运行时间.队列里可以等待的最多飞机数量,平均每个时间单元 ...

  2. javascript数据结构与算法---队列

    javascript数据结构与算法---队列 队列是一种列表,不同的是队列只能在队尾插入元素,在队首删除元素.队列用于存储按顺序排列的数据,先进先出,这点和栈不一样(后入先出).在栈中,最后入栈的元素 ...

  3. JavaScript数据结构与算法-队列练习

    队列的实现 // 队列类 function Deque () { this.dataStore = []; this.enqueueFront = enqueueFront; this.enqueue ...

  4. python数据结构与算法——队列

    队列结构可以使用数组来模拟,只需要设定头和尾的两个标记 参考自<啊哈> # 按书中的代码会出现索引越界的问题(书中申请了超量的空间) # 尝试令tai初始为len(q)-1则不会出错但少了 ...

  5. 每周一练 之 数据结构与算法(Queue)

    这是第二周的练习题,这里补充下咯,五一节马上就要到了,自己的计划先安排上了,开发一个有趣的玩意儿. 下面是之前分享的链接: 1.每周一练 之 数据结构与算法(Stack) 2.每周一练 之 数据结构与 ...

  6. C语言- 基础数据结构和算法 - 队列的顺序存储

    听黑马程序员教程<基础数据结构和算法 (C版本)>, 照着老师所讲抄的, 视频地址https://www.bilibili.com/video/BV1vE411f7Jh?p=1 喜欢的朋友 ...

  7. JS数据结构与算法-队列结构

    队列结构 一.认识队列 受限的线性结构: 我们已经学习了一种受限的线性结构:栈结构. 并且已经知道这种受限的数据结构对于解决某些特定问题,会有特别的 效果. 下面,我们再来学习另外一个受限的数据结构: ...

  8. JavaScript数据结构和算法----队列

    前言 队列和栈很像,只是用了不同的原则.队列是遵循先进先出(FIFO)原则的一组有序的的项,队列在尾部添加新元素,从顶部移除元素.最新添加的元素必须必须排队在队列的,末尾.可以想象食堂排队买饭的样子. ...

  9. js数据结构与算法——队列

    <script> //创建一个队列 function Queue(){ let items = []; //向队尾添加一个新的项 this.enqueue = function(eleme ...

随机推荐

  1. Eclipse启动认定SDK地址,出现Error executing aapt

    我把安卓的SDK安装在D盘,但是新建项目之后,提示的错误是 就是认定在F盘了,可是那个时候我只是在F盘启动了第一次,之后就拷贝到了D盘的, 是不是第一次启动就会注册了什么的呢? 解决方案: 更改你的e ...

  2. PS4 的下载速度问题

    折腾了好久了 AC68u路由自启动修改 hosts 问题,打算FQ另外改善 ps4 下载速度太慢问题. 后来看到几个dns, 直接修改后就速度超快,也不用在路由中添加了, 直接在 ps4 中网络设置中 ...

  3. plsql日期乱码

    乱码状况如截图: 控制面板\所有控制面板项\系统\高级系统设置\环境变量, 设置系统变量,变量名:NLS_LANG,变量值:Simplified Chinese_China.AL32UTF8改为SIM ...

  4. MySQL存储引擎之InnoDB

    一.The InnoDB Engine Each InnoDB table is represented on disk by an .frm format file in the database ...

  5. Java Web Service 学习

    参考原文: http://blog.csdn.net/ostrichmyself/article/details/6393627 http://www.cnblogs.com/Jessy/p/3528 ...

  6. sass初步认识3

    sass的混合器是对大段的样式代码进行命名,定义为混合器,以便被多次引用.混合器的格式为:“@mixin 样式名称{样式代码}”:调用混合器的格式为:“@include 样式名称”.例:@minin ...

  7. YTU 2989: 顺序表基本运算(线性表)

    2989: 顺序表基本运算(线性表) 时间限制: 1 Sec  内存限制: 128 MB 提交: 1  解决: 1 题目描述 编写一个程序,实现顺序表的各种基本运算(假设顺序表的元素类型为char), ...

  8. WPF中viewmodel层怎样得到view层的TabControl控件对象?

    View层: <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns: ...

  9. Floyd-Warshall算法,简称Floyd算法

    Floyd-Warshall算法,简称Floyd算法,用于求解任意两点间的最短距离,时间复杂度为O(n^3). 使用条件&范围通常可以在任何图中使用,包括有向图.带负权边的图. Floyd-W ...

  10. CPU和GPU实现julia

    CPU和GPU实现julia           主要目的是通过对比,学习研究如何编写CUDA程序.julia的算法还是有一定难度的,但不是重点.由于GPU实现了也是做图像识别程序,所以缺省的就是和O ...