队列是一种基于先进先出(FIFO)策略的集合类型。在应用程序中使用队列的主要原因是在用集合保存元素的同时保存它们的相对顺序:使他们的入列顺序和出列顺序一致
例如:
我们先将所有的整数读入队列中,然后使用Queue的size方法得到所需数组的大小,创建数组并将队列中的所有整数移动到数组中。
将数据移动到数组中,使用队列,之所以合适,是因为它能够将整数按照文件中的顺序放入到数组中(如果该顺序并不重要,也可以使用Bag对象)
package base.第一章.背包_队列_和栈.队列;
import java.util.Iterator;
/**
* Created by MK on 2018/7/18.
* 先进先出(FIFO)队列,链表实现
*/
public class Queue<Item> implements Iterable<Item> {
private Node first; //指向最早添加的节点
private Node last; //指向最近添加的节点
private int N; //节点的数量
private static class Node<Item> { //定义节点的嵌套类
Item item; //item代表的是所传入的值
Node next; //节点的指针
}
//因为是FIFO如果头部为空,则这个队列就为空了
public boolean isEmpty() {
return first == null; //或者是 N==0
}
int size() {
return N;
}
//入列操作(添加元素)
void enqueue(Item item) {
Node oldLast = last; //此时的last就是尾节点,此时的尾节点就变成了老节点
last = new Node(); //创建一个新的节点
last.item = item; //新节点的值是item
last.next = null; //新节点对应的指针就是null了,因为是先进先出的队列(类似于:类似火车过山洞,先进洞口的将指针指向,后入洞口的数据,最后的数据指向的就是null了)
if (isEmpty())
first = last; //队列为空,新节点就是头节点(即我第一次调用入列操作的时候(队列肯定为空),那时我就已经对头节点进行了赋值)
else
oldLast.next = last; //队列不为空的话,且上面已经进行了添加操作,因此将新节点赋值给老节点的指针,让其指向新节点的地址
N++;
}
//出列操作(删除最早添加的元素)
Item dequeue() {
/*
* 你怎么就能确定我first就是第一个元素呢?因为在上面有设置
* */
Item item = (Item) first.item; //得到头节点的值
first = first.next; //将头节点的指针,赋值给下一个新的头节点(寓意是跳过)
if (isEmpty()) {
last = null; //队列为空的话,则将尾节点赋值为空
}
N--;
return item;
}
@Override
public Iterator<Item> iterator() {
return new ListIterator();
}
private class ListIterator implements Iterator<Item> {
private Node current = first;
@Override
public boolean hasNext() {
return current != null;
}
@Override
public Item next() {
Item item = (Item) current.item;
current = current.next;
return item;
}
}
}
队列测试
package base.第一章.背包_队列_和栈.队列;
import edu.princeton.cs.algs4.StdOut;
import java.util.Arrays;
/**
* Created by MK on 2018/7/17.
* 测试:迭代的集合类型
* 例子:将队列中的数据移动到数组中
*/
public class 队列测试 {
public static void main(String[] args) {
// Bag<String> bag = new Bag<String>();
// while (!StdIn.isEmpty()) {
// String item = StdIn.readString();
// bag.add(item);
// }
Queue<Integer> bag = new Queue<Integer>();
bag.enqueue(3);
bag.enqueue(2);
bag.enqueue(4);
StdOut.println("size of Bag= " + bag.size());
// StdOut.println(bag.size());
//这里的Bag之所以能够循环,是因为实现了Iterable (可迭代的集合类型)
for (Integer res : bag) {
StdOut.println(res);
}
int n = bag.size();
int[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = bag.dequeue();
}
StdOut.println(Arrays.toString(a));
}
}