数据结构(四)队列"/>
数据结构(四)队列
本文目录
1 什么是队列
2 如何使用队列
3 Java中的队列Queue接口
3.1 Queue接口的定义
3.2 添加方法
3.3 移除方法
3.4 获取元素
4 Java中队列Queue接口的实现类
4.1 队列的抽象接口AbstractQueue
4.2 队列的实现类
4.2.1 没有实现阻塞接口的实现类
4.2.2 实现阻塞接口的实现类
4.3 优先级队列PriorityQueue
4.3.1 PrioprityQueue源码定义
4.3.2 PrioprityQueue中的方法
1 什么是队列
队列是一种用于存储数据的数据结构(与链表和栈类似)。数据到达的次序是队列的关键。在日常生活中队列是指从序列的开始按照顺序排列等待服务的一队人或物。
队列的定义:队列是一种只能在一端插入(队尾),在另一端删除(队首)的有序线性表。队列中第一个插入的元素也是第一个被删除的元素。所以,队列是一种先进先出(FIFO)或后进后出(LILO)线性表。
与栈类似,两个改变队列的操作各有专用名称,在队列中插入一个元素,称为入队(DeQueue),从队列中删除一个元素,称为出队(DeQueue)。试图对一个空队列执行出队操作称为下溢(underflow),试图对一个满队列执行入队操作称为溢出(overflow)。通常认为下溢和溢出是异常。
2 如何使用队列
可以通过在售票柜台前排队购票的例子来理解队列的概念。新来购票的人只能从队尾开始排队等待,而队列最前面的人将是下一个被服务的对象,他将离开队列去柜台前买票。然后,他的下一位排队者将成为队列中的第一个人,并且将成为下一个离开队列去柜台前买票的人。随着队列中最前面的人不断离开队列,其他人都随之想队列前面移动,最后,队列中的每个人都会依次到达队首,然后离开队列去接受服务。当需要维持一个先后次序(或到达次序)时,采用队列是非常有用的,
3 Java中的队列Queue接口
在Java语言中,Java util包中的Queue接口给出了队列抽象数据类型中的基本操作。Queue接口中定义的方法如下:
3.1 Queue接口的定义
JDK中队列Queue的源码定义如下:
public interface Queue<E> extends Collection<E> {
}
可以看到,Queue继承了Collections接口。Queue接口与List、Set接口同一级别,都是继承了Collections接口。
注意:队列中的插入和删除必须遵守先进先出原则。
3.2 添加方法
(1)添加方法add定义如下:
/*** Inserts the specified element into this queue if it is possible to do so* immediately without violating capacity restrictions, returning* {@code true} upon success and throwing an {@code IllegalStateException}* if no space is currently available.** @param e the element to add* @return {@code true} (as specified by {@link Collection#add})* @throws IllegalStateException if the element cannot be added at this* time due to capacity restrictions* @throws ClassCastException if the class of the specified element* prevents it from being added to this queue* @throws NullPointerException if the specified element is null and* this queue does not permit null elements* @throws IllegalArgumentException if some property of this element* prevents it from being added to this queue*/boolean add(E e);
该插入指定的元素,插入如果立即可行且不会违反容量限制,返回此队列true成功;如果当前没有空间可用,抛出IllegalStateException异常。
(2)offer方法定义如下:
/*** Inserts the specified element into this queue if it is possible to do* so immediately without violating capacity restrictions.* When using a capacity-restricted queue, this method is generally* preferable to {@link #add}, which can fail to insert an element only* by throwing an exception.** @param e the element to add* @return {@code true} if the element was added to this queue, else* {@code false}* @throws ClassCastException if the class of the specified element* prevents it from being added to this queue* @throws NullPointerException if the specified element is null and* this queue does not permit null elements* @throws IllegalArgumentException if some property of this element* prevents it from being added to this queue*/boolean offer(E e);
该方法将指定的元素插入此队列中,如果它是立即可行且不会违反容量限制。 当使用有容量限制的队列,这种方法通常是优选的。add仅通过抛出异常,后者可能无法插入的元件。
3.3 移除方法
(1)移除方法remove:
/*** Retrieves and removes the head of this queue. This method differs* from {@link #poll() poll()} only in that it throws an exception if* this queue is empty.** @return the head of this queue* @throws NoSuchElementException if this queue is empty*/E remove();
检索并移除此队列的头。 此方法不同于poll(),仅在如果此队列为空抛出异常。
(2)移除方法poll:
/*** Retrieves and removes the head of this queue,* or returns {@code null} if this queue is empty.** @return the head of this queue, or {@code null} if this queue is empty*/E poll();
获取并移除此队列的头,或者返回null ,如果此队列为空。
3.4 获取元素
(1)获取元素方法element()
/*** Retrieves, but does not remove, the head of this queue. This method* differs from {@link #peek peek} only in that it throws an exception* if this queue is empty.** @return the head of this queue* @throws NoSuchElementException if this queue is empty*/E element();
获取,但不移除此队列的头。 从该方法不同于peek仅在于:它将抛出异常,如果此队列是空的。
(2)获取方法peek()
Queue接口中源码定义如下:
/*** Retrieves, but does not remove, the head of this queue,* or returns {@code null} if this queue is empty.** @return the head of this queue, or {@code null} if this queue is empty*/E peek();
获取但不移除此队列的头,或者返回null ,如果此队列为空。
4 Java中队列Queue接口的实现类
4.1 队列的抽象接口AbstractQueue
队列的抽象接口AbstractQueue接口继承了Queue接口,并进一步提供方法。源码定义如下:
public abstract class AbstractQueue<E>extends AbstractCollection<E>implements Queue<E> {
}
可以看到,AbstractQueue接口继承了AbstractCollections集合的抽象接口并实现了Queue队列接口。它提供的方法定义有如下:
可以看到,它从AbstractCollection、Queue接口中分别继承和实现了添加方法(add)、删除方法(remove)、获取队头元素方法(element)、清空队列方法(clear)、批量入队方法(addAll)。
4.2 队列的实现类
AbstractQueue接口实现了Queue接口,队列的实现类都是继承自AbstractQueue抽象类的。队列的实现类总结主要有如下:
4.2.1 没有实现阻塞接口的实现类
(1)LinkedList:实现了List<E>接口和双端队列Deque<E>接口;
(2)内置的不阻塞队列:PrioprityQueue和ConcurrentLinkedQueue:
PriorityQueue 类实质上维护了一个有序列表。加入到 Queue 中的元素根据它们的天然排序(通过其 java.util.Comparable 实现)或者根据传递给构造函数的 java.util.Comparator 实现来定位。
ConcurrentLinkedQueue 是基于链接节点的、线程安全的队列。并发访问不需要同步。因为它在队列的尾部添加元素并从头部删除它们,所以只要不需要知道队列的大 小,ConcurrentLinkedQueue 对公共集合的共享访问就可以工作得很好。收集关于队列大小的信息会很慢,需要遍历队列。
4.2.2 实现阻塞接口的实现类
java.util.concurrent包中加入了BlockingQueue 接口和五个阻塞队列类。它实质上就是一种带有一点扭曲的 FIFO 数据结构。不是立即从队列中添加或者删除元素,线程执行操作阻塞,直到有空间或者元素可用。
五个队列所提供的各有不同:
(1)ArrayBlockingQueue :一个由数组支持的有界队列。
(2)LinkedBlockingQueue :一个由链接节点支持的可选有界队列。
(3) PriorityBlockingQueue :一个由优先级堆支持的无界优先级队列。
(4)DelayQueue :一个由优先级堆支持的、基于时间的调度队列。
(5) SynchronousQueue :一个利用 BlockingQueue 接口的简单聚集(rendezvous)机制。
4.3 优先级队列PriorityQueue
在很多实际应用中,我们通常需要按照优先级情况对待处理对象进行处理,比如首先处理优先级最高的对象,然后处理次高的对象。最简单的一个例子就是,在手机上玩游戏的时候,如果有来电,那么系统应该优先处理打进来的电话。在这种情况下,我们的数据结构应该提供两个最基本的操作,一个是返回最高优先级对象,一个是添加新的对象。这种数据结构就是优先级队列(Priority Queue) 。
优先级队列和通常的栈和队列一样,只不过里面的每一个元素都有一个”优先级”,在处理的时候,首先处理优先级最高的。如果两个元素具有相同的优先级,则按照他们插入到队列中的先后顺序处理。优先级队列可以通过链表,数组,堆或者其他数据结构实现。
4.3.1 PrioprityQueue源码定义
源码定义如下:PrioprityQueue继承了AbstractQueue抽象类,并实现了序列化。
public class PriorityQueue<E> extends AbstractQueue<E>implements java.io.Serializable {
}
4.3.2 PrioprityQueue中的方法
PrioprityQueue类中的方法众多,如下图:
PriorityQueue中的方法很详尽,我们常用的基本是入队、出队方法、获取队首元素、队列大小、判断队列是否为空等方法。具体实现可看源码,此处不做具体阐述。
更多推荐
数据结构(四)队列
发布评论