队列的简单实现(一)

来源:互联网 发布:学java电脑配置 编辑:程序博客网 时间:2024/05/17 10:26

与栈相似的线性结构还有一种,那就是队列。

栈遵循后进先出(Last In First Out, LIFO)原则,而队列则恰好相反,遵循先进先出(First In First Out, FIFO)原则。

与栈相同,从存储结构来对队列进行划分,队列可以分为两类:

  • 顺序队列结构:用一组地址连续的内存单元依次保存队列中的数据。
  • 链式队列结构:用链表的形式保存队列中的数据。

如上图所示,队列是两端操作,入队列的一端为队尾,而出队列的一端为队头。一般的队列的基本操作有两个:

  1. 入队列(Enter):将数据保存到队列尾部。
  2. 出队列(Out):将对头的数据弹出(读取后删除)。
这里先简单实现顺序队列结构,之后再实现链式队列结构。

代码如下:

package ds.queue;public class Queue<E> {private static final int MAX_LENGTH = 20;// 队列的默认最大长度private Object[] objData = null; // 存放队列的数据的数组private int nHead;// 用于标记队列头部下标private int nTail;// 用于标记队列尾部下标private int nLen;// 用于记录队列初始化时的最大长度/** * 初始化队列,默认队列长度为50 */Queue() {this(MAX_LENGTH);}/** * 初始化队列 *  * @param nInitSize *            队列的最大长度 */Queue(int nInitSize) {if (nInitSize > 0) {objData = new Object[nInitSize];nLen = nInitSize;nHead = 0;nTail = -1;} else {System.out.println("栈的初始化长度不能小于等于0:" + nInitSize);}}/** * 获取队列的已使用的长度 *  * @param queue *            队列的引用 * @return 队列已使用的长度 */int getSize(Queue<E> queue) {// if (nHead == 0 && nTail == -1) {// return 0;// }if (nHead > nTail) {return 0;}return (queue.nTail - queue.nHead + 1);}/** * 判断队列是否空 *  * @param queue *            队列的引用 * @return 若队列为空,则返回true,否则返回false */boolean isEmpty(Queue<E> queue) {return (getSize(queue) == 0);}/** * 判断队列是否满 *  * @param queue *            队列的引用 * @return 若队列为满,则返回true,否则返回false */boolean isFull(Queue<E> queue) {return (queue.nTail + 1 == nLen);}/** * 清空队列,但不释放内存 *  * @param queue *            队列的引用 */void clear(Queue<E> queue) {nHead = 0;nTail = -1;}/** * 清空队列,并释放内存 *  * @param queue *            队列的引用 */void free(Queue<E> queue) {clear(queue);if (queue != null) {queue = null;}}/** * 入队列 *  * @param queue *            队列的引用 * @param eData *            入队列的数据 */void enter(Queue<E> queue, E eData) {if (isFull(queue)) {System.out.println("队列已满,无法入队列:" + eData);return;}queue.objData[++queue.nTail] = eData;System.out.println(eData + "已入队列");}/** * 出队列 *  * @param queue *            队列的引用 * @return 队列头部的数据 */@SuppressWarnings("unchecked")E out(Queue<E> queue) {if (isEmpty(queue)) {System.out.println("队列已空,无法出队列");return null;}System.out.println((E) queue.objData[queue.nHead] + "出队列");return (E) queue.objData[queue.nHead++];}/** * 读取队列头部数据 *  * @param queue *            队列的引用 * @return 队列头部的数据 */@SuppressWarnings("unchecked")E peek(Queue<E> queue) {if (isEmpty(queue)) {System.out.println("队列已空,无法读取队列头部");return null;}System.out.println((E) queue.objData[queue.nHead] + "已读取");return (E) queue.objData[queue.nHead];}}

测试代码:

package ds.queue;public class Simple {public static void main(String[] args) {System.out.println("----新建空队列----");Queue<String> queue = new Queue<String>(5);System.out.println("队列的现有长度:" + queue.getSize(queue));System.out.println("----测试入队列操作----");for (int i = 0; i < 6; i++) {System.out.println("将test" + i + "压入队列");queue.enter(queue, "test" + i);}System.out.println("队列的现有长度:" + queue.getSize(queue));System.out.println("----测试读取队列顶操作----");queue.peek(queue);queue.peek(queue);System.out.println("----测试出队列操作----");for (int i = 0; i < 7; i++) {queue.out(queue);}System.out.println("队列的现有长度:" + queue.getSize(queue));}}

测试结果:

----新建空队列----队列的现有长度:0----测试入队列操作----将test0压入队列test0已入队列将test1压入队列test1已入队列将test2压入队列test2已入队列将test3压入队列test3已入队列将test4压入队列test4已入队列将test5压入队列队列已满,无法入队列:test5队列的现有长度:5----测试读取队列顶操作----test0已读取test0已读取----测试出队列操作----test0出队列test1出队列test2出队列test3出队列test4出队列队列已空,无法出队列队列已空,无法出队列队列的现有长度:0

上述代码实现的队列是队列长度不可变的顺序队列结构,这里就不再实现队列长度可变的顺序队列结构了。

如需队列长可变的读者,可以根据栈的简单实现(二)进行相应的改动即可。

原创粉丝点击