上一篇文章写了栈的相关知识,而本文会讲一下队列
队列是一种特殊的线性表,在尾部插入(入队Enqueue),从头部删除(出队Dequeue),和栈的特性相反,存取数据特点是:FIFO
Java中queue源码:
public interface Queue<E> extends Collection<E> {
boolean add(E e); //添加一条数据到队尾,成功返回true,否则false
boolean offer(E e); //添加一条数据到队尾,如果队列满了,会返回null
E remove(); //从队头删除一条数据,如果是空队列,会发生异常
E poll(); //从队头删除一条数据,如果是空队列,会返回null
E element(); //返回队头的数据,如果是空队列,会发生异常
E peek(); //返回队头的数据,如果是空队列,会返回null
}
queue直接继承Collection,有6个基本方法实现增删查的功能
单向队列:
PS:删除的数据还是保存在内存中的,只是不能被访问,因为front位置移动了
上图中第二步,我们从队头front删除一些数据,然后队尾由于插入数据,rear移动到最后,此时无法插入数据
为了避免队列不满但是不能插入数据的情况,采用第三步:循环队列,将队尾回绕到队列开始的位置
Java代码实现单向队列:
public class MyQueue<E> {
private int maxSize; //队列总大小
private Object[] elementData; //保存数据的数组
private int front; //队头
private int rear; //队尾
private int nItems; //队列元素的数量
public MyQueue(int value) {
maxSize = value;
elementData = new Object[value];
front = 0;
rear = -1;
nItems = 0;
}
public void add(E e) {
if (isFull()) {
System.out.println("当前队列已满");
} else {
if (rear == maxSize - 1) { //如果rear已经指向最后面,将队尾回绕到队列开始的位置
rear = -1;
}
elementData[++rear] = e; //rear后移一位(首位为0),并且插入数据
nItems++; //元素数量+1
}
}
//移除数据
public E remove(){
E temp = null;
if (isEmpty()) {
System.out.println("当前为空队列,无法删除");
} else {
temp = (E)elementData[front++]; //返回队头front的数据,然后front后移一位
if (front == maxSize) { //如果front已经后移到最末尾了,front重置
front = 0;
}
nItems--; //元素数量-1
}
return temp;
}
public E peek(){ //查看队头数据
return (E)elementData[front];
}
public boolean isFull(){
return (nItems == maxSize);
}
public boolean isEmpty(){
return (nItems ==0);
}
public int getSize(){ //返回队列的大小
return nItems;
}
}
public static void main(String[] args) {
MyQueue<Integer> queue = new MyQueue<>(5);
int i = 0;
while (!queue.isFull()) {
queue.add(i++);
}
queue.add(6); //当前队列已满,无法添加了
while (!queue.isEmpty()) {
queue.remove();
}
}
输出结果:当前队列已满
优先级队列:
优先级队列是比栈和队列更专用的数据结构,一般情况下,和浦东队列一样,优先级队列有一个头部和一个尾部,也是从头部移除数据。
不过优先级队列中,元素按照关键字是有序的。关键字最小的元素总是在头部,元素在插入的时候按照顺序插入到合适的位置以确保队列的顺序
优先级队列在程序中也有很多应用,例如:图的最小生成树
这里我们使用简单数组实现优先级队列,这种方式比较慢,但是很简单。优先级队列一般都是通过队来实现,在后面会降到
代码实现:
public class MyPriorityQueue {
private int maxSize; //队列总大小
private Object[] elementData; //保存数据的数组
private int nItems; //队列元素的数量
public MyPriorityQueue(int value) {
maxSize = value;
elementData = new Object[value];
nItems = 0;
}
public boolean add(int e) { //添加元素,关键字小的元素在头部,通过插入排序实现
int j;
if (nItems == 0) {
elementData[nItems++] = e;
} else {
j = nItems - 1;
while (j >= 0 && e > (int)elementData[j]) {
elementData[j+1] = elementData[j];
j--;
}
elementData[j+1] = e;
nItems++;
}
return true;
}
//移除数据
public Object remove(){ //删除一条数据,返回老数据
Object value = elementData[nItems-1];
elementData[nItems-1] = null;
nItems--;
return value;
}
public Object peekMin() { //返回优先级最高的元素
return elementData[nItems-1];
}
//判断是否为空
public boolean isEmpty(){
return (nItems == 0);
}
//判断是否满了
public boolean isFull(){
return (nItems == maxSize);
}
}
public static void main(String[] args) {
MyPriorityQueue queue = new MyPriorityQueue(5);
int i = 0;
while (!queue.isFull()) {
queue.add(i++);
}
while (!queue.isEmpty()) {
System.out.println(queue.peekMin());;
queue.remove();
}
}
打印结果:
0
1
2
3
4
add()通过插入排序实现,时间复杂度O(N),如果忘记插入排序,可以参考:Java数据结构和算法(三)--三大排序--冒泡、选择、插入排序
PS:Queue一般作为程序的某种实现,而不是用来保存数据
内容参考:<Java数据结构和算法>
来源:oschina
链接:https://my.oschina.net/u/4330970/blog/3492345