队列是一种特殊的线性表,先进先出(first in first out)FIFO,它只允许在表的前端(front)进行删除操作,只允许在表的后端(rear)进行插入操作。
实际应用:排队等待公交车,银行或者超市里的等待列队
出现假溢出的时候的一般解决方法:
一是将队列元素向前平移,对应的队列的顺序存储结构及实现中的a实现
二循环队列,对应的循环队列实现
1.队列的顺序存储结构及实现
a.没有控制队列容量大小的普通队列,数组移位实现(无假溢出现象)
package collectionsFramework.queue; /** * @Package collectionsFramework.queue * @ClassName: SequenceQueue * @Description: TODO(这里用一句话描述这个类的作用) * @author andy * @date 2013-11-21 下午05:26:10 */ public class SequenceQueue<T> { //队列个数 private int size; //装载元素的数组 private Object[] elementData; //默认容量大小 private int defaultCapacity = 16; //容量大小 private int capacity; //增量大小 private int incrementCapacity; public SequenceQueue(){ elementData = new Object[defaultCapacity]; } public SequenceQueue(int capacity){ this.capacity = capacity; elementData = new Object[capacity]; } public SequenceQueue(int capacity,int incrementCapacity){ this(capacity); this.incrementCapacity = incrementCapacity; } //入列 public synchronized T add(T element){ if(null == element){ return null; } boolean flag = true; try { ensureCapacity(); } catch (Exception e) { try { ensureCapacity(); } catch (Exception e1) { flag = false; try { throw new Exception("第二次数组扩容失败!"); } catch (Exception e2) { e2.printStackTrace(); } } } if(flag){ elementData[size++] = element; return element; } return null; } //出列 public synchronized T poll(){ if(size == 0){ return null; } Object[] oldData = elementData; elementData = new Object[elementData.length]; try { System.arraycopy(oldData, 1, elementData, 0, elementData.length - 1); } catch (Exception e) { try { throw new Exception("移除元素,数组元素往前移植时出错"); } catch (Exception e1) { e1.printStackTrace(); } e.printStackTrace(); } size--; return (T)oldData[0]; } //移除头部元素,但不删除 public synchronized T peek(){ if(0 == size){ return null; } return (T)elementData[0]; } //确保容量够 private synchronized void ensureCapacity() { if(size == elementData.length){ int length = 0; if(incrementCapacity > 0){ length = elementData.length + length; }else{ length = elementData.length<<1; } Object[] oldData = elementData; elementData = new Object[length]; try { System.arraycopy(oldData, 0, elementData, 0, size-1); } catch (Exception e) { try { throw new Exception("第一次数组扩容失败!"); } catch (Exception e1) { e1.printStackTrace(); } } } } public String toString() { if (0==size) { return "[]"; } else { StringBuilder sb = new StringBuilder("["); for (int i = 0; i < size; i++) { sb.append(elementData[i].toString() + ", "); } int len = sb.length(); return sb.delete(len - 2, len).append("]").toString(); } } public static void main(String[] args) { SequenceQueue<String> queue = new SequenceQueue<String>(10); for(int i = 0; i<100; i++){ System.out.println("元素:" + queue.add("a" + i) + " 入列"); System.out.println("字符串:" + queue); if(queue.size == queue.capacity){ System.out.println("已经有"+queue.capacity+"个未运行的任务数"); System.out.println("元素:" + queue.poll() + "---------出列"); } } while(queue.size != 0){ System.out.println("字符串:" + queue); System.out.println("元素:" + queue.poll() + " 出列"); } } }
b.控制了容量大小的队列(会有假溢出现象)
package collectionsFramework.queue; import java.util.Arrays; /** * @Package collectionsFramework.queue * * @ClassName: SequenceQueue2 * * @Description: TODO(这里用一句话描述这个类的作用) * * @author andy * * @date 2013-11-24 下午06:52:39 */ public class SequenceQueue3<T> { private int DEFAULT_SIZE = 10; // 保存数组的长度。 private int capacity; // 定义一个数组用于保存顺序队列的元素 private Object[] elementData; // 保存顺序队列中元素的当前个数 private int front = 0; private int rear = 0; // 以默认数组长度创建空顺序队列 public SequenceQueue3() { capacity = DEFAULT_SIZE; elementData = new Object[capacity]; } // 以一个初始化元素来创建顺序队列 public SequenceQueue3(T element) { this(); elementData[0] = element; rear++; } /** * 以指定长度的数组来创建顺序队列 * * @param element * 指定顺序队列中第一个元素 * @param initSize * 指定顺序队列底层数组的长度 */ public SequenceQueue3(T element, int initSize) { this.capacity = initSize; elementData = new Object[capacity]; elementData[0] = element; rear++; } // 获取顺序队列的大小 public int length() { return rear - front; } // 插入队列 public T add(T element) { if (rear > capacity - 1) { throw new IndexOutOfBoundsException("队列已满的异常"); } elementData[rear++] = element; return element; } // 移除队列 public T remove() { if (empty()) { throw new IndexOutOfBoundsException("空队列异常"); } // 保留队列的rear端的元素的值 T oldValue = (T) elementData[front]; // 释放队列的rear端的元素 elementData[front++] = null; return oldValue; } // 返回队列顶元素,但不删除队列顶元素 public T element() { if (empty()) { throw new IndexOutOfBoundsException("空队列异常"); } return (T) elementData[front]; } // 判断顺序队列是否为空队列 public boolean empty() { return rear == front; } // 清空顺序队列 public void clear() { // 将底层数组所有元素赋为null Arrays.fill(elementData, null); front = 0; rear = 0; } public String toString() { if (empty()) { return "[]"; } else { StringBuilder sb = new StringBuilder("["); for (int i = front; i < rear; i++) { sb.append(elementData[i].toString() + ", "); } int len = sb.length(); return sb.delete(len - 2, len).append("]").toString(); } } public static void main(String[] args) { SequenceQueue3<String> queue = new SequenceQueue3<String>(); for (int i = 0; i < queue.capacity; i++) { System.out.println("元素:" + queue.add("a" + i) + "入列"); } /*int j = 0; while (!queue.empty()) { j++; System.out.println("元素:" + queue.remove() + "+++++++++++++++++=====出列"); if (!queue.empty()) { System.out.println("元素:" + queue.add("j" + j) + "入列"); } if (100 == j) { break; } }*/ while (!queue.empty()) { System.out.println("元素:" + queue.remove() + "出列"); } } }
2.队列的链式存储结构及实现
package collectionsFramework.queue; /** * @Package collectionsFramework.queue * * @ClassName: LinkQueue * * @Description: TODO(这里用一句话描述这个类的作用) * * @author andy * * @date 2013-11-24 下午10:30:26 */ public class LinkQueue<T> { // 定义一个内部类Node,Node实例代表链队列的节点。 private class Node { // 保存节点的数据 private T data; // 指向下个节点的引用 private Node next; // 无参数的构造器 public Node() { } // 初始化全部属性的构造器 public Node(T data, Node next) { this.data = data; this.next = next; } } // 保存该链队列的头节点 private Node front; // 保存该链队列的尾节点 private Node rear; // 保存该链队列中已包含的节点数 private int size; // 创建空链队列 public LinkQueue() { // 空链队列,front和rear都是null front = null; rear = null; } // 返回链队列的长度 public int length() { return size; } // 将新元素加入队列 public T add(T element) { if (size == 0) { front = new Node(element, null); rear = front; } else { //rear = new Node(element, null);//这些写虽然有下一个结点,但是当前结点对下个结点的引用都是空的 //创建新节点 Node newNode = new Node(element , null); //让尾节点的next指向新增的节点 rear.next = newNode; //以新节点作为新的尾节点 rear = newNode; } size++; return element; } // 访问链式队列中最后一个元素 public T element() { return rear.data; } // 判断链式队列是否为空队列 public boolean empty() { return size == 0; } // 删除队列front端的元素 public T remove() { if (0 != size) { // 保存之前的前端结点 Node oldFront = front; // 前端结点移除就没有了,所以将前端的下个节点设置为新的前端结点,并把将要移除的前端结点的对下个结点的引用设为null Node newfront = front.next; front.next = null; front = newfront; size--; return oldFront.data; } else { return null; } } // 清空链队列 public void clear() { // 将front、rear两个节点赋为null front = null; rear = null; size = 0; } public String toString() { // 链队列为空链队列时 if (empty()) { return "[]"; } else { StringBuilder sb = new StringBuilder("["); for (Node current = front; current != null; current = current.next) { sb.append(current.data.toString() + ", "); } int len = sb.length(); return sb.delete(len - 2, len).append("]").toString(); } } public static void main(String[] args) { LinkQueue<String> queue = new LinkQueue<String>(); for(int i = 0; i<100; i++){ System.out.println("元素:" + queue.add("a" + i) + " 入列"); System.out.println("字符串表示:" + queue); if(queue.size == 20){ System.out.println("已经有"+"20"+"个未运行的任务数"); System.out.println("元素:" + queue.remove() + "---------出列"); } } //queue.clear(); while(queue.size != 0){System.out.println("字符串表示:" + queue); System.out.println("元素:" + queue.remove() + " 出列"); } } }
3.循环队列(顺序结构存储实现)
package collectionsFramework.queue; /** * @Package collectionsFramework.queue * * @ClassName: LoopQueue * * @Description: TODO(这里用一句话描述这个类的作用) * * @author andy * * @date 2013-11-24 下午11:32:52 */ public class LoopQueue<T> { private int DEFAULT_SIZE = 10; // 保存数组的长度。 private int capacity; // 定义一个数组用于保存循环队列的元素 private Object[] elementData; private int front = -1; private int rear = -1; // 以默认数组长度创建空循环队列 public LoopQueue() { capacity = DEFAULT_SIZE; elementData = new Object[capacity]; } // 判断是否为空 private boolean empty() { return front == -1; } // 判断栈是否满了 public boolean isFull() { return (rear + 1) % capacity == front; } // 置空 public void clear() { front = rear = -1; } //元素个数 /*public int length() { if (empty()) { return 0; } return (rear - front + capacity) % capacity; }*/ public int length() {// 队列长度 if(empty()){ return 0; } if (rear >= front) return rear - front + 1; else return capacity - (front - rear) + 1; } // 插入队列 public T add(T element) { if (isFull()) { System.out.println("队列已经满了"); return null; } if (empty()) { front = rear = 0; } else { rear = (rear + 1) % capacity; } elementData[rear] = element; return element; } // 移除队列顶部元素 public T remove() { if (empty()) { System.out.println("空队列"); throw new IndexOutOfBoundsException("空队列异常"); } T oldData = (T) elementData[front]; elementData[front] = null; if (front == rear) { clear(); return oldData; } front = (front + 1) % capacity; return oldData; } // 返回队列顶部元素,但不删除元素 public T element() { if (empty()) { return null; } return (T) elementData[front + 1]; } public String toString() {// 打印所有元素 if (empty()) { return "[]"; }else{ StringBuilder sb = new StringBuilder("["); int i = front; int j = 0; while(j < length()){ sb.append(elementData[i].toString() + ", "); i = (i + 1) % capacity; j++; } /*for (int j = 0; j < length(); i = (i + 1) % capacity, j++){ sb.append(elementData[i].toString() + ", "); }*/ int len = sb.length(); return sb.delete(len - 2, len).append("]").toString(); } } public static void main(String[] args) { LoopQueue<String> queue = new LoopQueue<String>(); for (int i = 0; i < 100; i++) { System.out.println("元素:" + queue.add("a" + i) + " 入列"); System.out.println("字符串表示:" + queue); if(queue.length() == queue.capacity){ System.out.println("元素:"+queue.remove() + " +++++++++++++出列"); } //System.out.println("元素长度:" + queue.length()); } //queue.clear(); while(queue.length() != 0){ System.out.println("字符串表示:" + queue); System.out.println("元素:"+queue.remove() + " 出列"); } } }