【数据结构和算法】之队列
一、概念
先进者先出,这就是典型的“队列”。
二、队列和栈
队列跟栈一样,也是一种操作受限的线性表数据结构。
三、队列的种类和队列的实现
- 顺序队列:用数组实现的队列 (代码实现的关键点:确定好队空和队满的判定条件)
当前队列中的数据为: 队头>h->i->j->队尾
向队列中依次添加a,b元素后,队列的数据信息:队头>h->i->j->a->b->队尾
- 链式队列:用链表实现的队列
1、循环队列(尾进头出)
循环对列判断队空的条件:head==tail
循环队列队满的条件:(tail+1)%n=head [队列会空一格位置]
数组方式一(普通队列)
public class CircularQueue { // 数组:items,数组大小:n private String[] items; private int n = 0; // head表示队头下标,tail表示队尾下标 private int head = 0; private int tail = 0; // 申请一个大小为capacity的数组 public CircularQueue(int capacity) { items = new String[capacity]; n = capacity; } // 入队 public boolean enqueue(String item) { // 队列满了 if ((tail + 1) % n == head) return false; items[tail] = item; tail = (tail + 1) % n; return true; } // 出队 public String dequeue() { // 如果head == tail 表示队列为空 if (head == tail) return null; String ret = items[head]; head = (head + 1) % n; return ret; } }
2、阻塞队列(线程安全)
数组方式一(阻塞并发队列)
/** * 队列的规则:尾巴进度,头节点出队 * 判断队列是否为空: headIndex == tailIndex * 判断队列是否已经满了:(tailIndex+1) % tab.length == headIndex **/ public class ArrayQueue { public static void main(String[] args) { ArrayQueue arrayQueue = new ArrayQueue(10); arrayQueue.addData(1); arrayQueue.addData(2); arrayQueue.addData(3); arrayQueue.addData(4); arrayQueue.addData(5); arrayQueue.addData(6); arrayQueue.addData(7); arrayQueue.addData(8); arrayQueue.addData(9); arrayQueue.addData(10); arrayQueue.pullData(); arrayQueue.addData(11); for(int i=0;i<10;i++){ System.out.println(arrayQueue.pullData()); } } private final Object lock = new Object(); private int count; private int maxSize; private int[] tab; private int headIndex; private int tailIndex; public ArrayQueue(int size) { this.count = 0; this.maxSize = size; this.tab = new int[size + 1]; } /** * 下一个将要插入元素的位置 * * @return额 */ public int nextInsertIndex() { return (this.tailIndex + 1) % this.tab.length; } /** * 添加一个元素 * * @param data */ public void addData(int data) { synchronized (lock) { //判断队列是否已经满了 while (nextInsertIndex() == headIndex) { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //设置元素 tab[this.tailIndex] = data; this.tailIndex++; this.count++; //唤醒线程 lock.notifyAll(); } } /** * 取出一个元素 * * @return */ public int pullData() { synchronized (lock) { //如果头指针和尾巴指针在一个位置上,则表示队里为空,需要等待 while (this.headIndex == this.tailIndex) { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //取出元素 int result = tab[headIndex]; this.headIndex++; this.count--; //唤醒等待添加元素的线程 lock.notifyAll(); return result; } } }
链表方式二(阻塞并发队列)
/** * 尾巴进队,头节点出队 * 判断队列已满:队列数据个数== 最大数 * 判断队列已经空:头节点=尾巴节点 * 取数据时判断队列为空:头节点.next.next==null **/ public class LinkQueue { public static void main(String[] args) { LinkQueue linkQueue = new LinkQueue(10); linkQueue.putData(1); linkQueue.putData(2); linkQueue.putData(3); linkQueue.putData(4); linkQueue.putData(5); linkQueue.putData(6); linkQueue.putData(7); linkQueue.putData(8); linkQueue.putData(9); linkQueue.putData(10); linkQueue.pullData(); linkQueue.putData(11); for(int i=0;i<10;i++){ System.out.println(linkQueue.pullData()); } } private final Node tag = new Node(-1); private final Object lock = new Object(); private Node head; private Node tail; private int max; private int count; public LinkQueue(int capacity) { this.max = capacity; this.head = this.tail = tag; this.count = 0; } /** * 放入一个数据 * * @param value */ public void putData(int value) { synchronized (lock) { //step1:判断队列是否已经满了 while (this.count == this.max) { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //step2:添加元素 Node waitInsertNode = new Node(value); if (this.tail == this.head) { //表示队列为空 this.head.nexNode = waitInsertNode; waitInsertNode.preNode = this.head; this.tail = waitInsertNode; } else { waitInsertNode.preNode = this.tail; this.tail.nexNode = waitInsertNode; this.tail = waitInsertNode; } this.count++; this.lock.notifyAll(); } } /** * 取出一个数据 * * @return */ public int pullData() { synchronized (lock) { //step1:判断队列是否为空队列 while (this.tail == this.head) { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //step2:取出数据 Node result = this.head.nexNode; int value = result.value; Node nexTag = result.nexNode; result.preNode = null; this.count--; if (nexTag != null) { //队列中还有其他元素 nexTag.preNode = this.head; this.head.nexNode = nexTag; } else { //队列中没有元素 this.head.nexNode = null; this.tail = this.head; } //step3:唤醒其他线程 this.lock.notifyAll(); return value; } } private static class Node { private Node nexNode; private Node preNode; private int value; public Node(int value) { this.value = value; } } }