基本定义
在计算机科学中,queue是以顺序的方式维护的一组数据集合,在一端添加数据,从另一端添加数据。习惯来说,添加的一端为尾,移除的一端为头,就如同生活中的排队买商品。
环形链表实现队列
只要根据队列的基本定义和链表的语法,就可以很轻松的写出队列的方法
特殊:
队列需要有容量限制的,删除和添加只在头尾,不可在中间插入
定义队列的接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| public interface Queue<E> {
boolean offer(E value);
E pool();
E peek();
boolean isEmpty();
boolean isFull(); }
|
环形链表作为接口的实现类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
| public class LinkedListQueue<E> implements Queue<E>, Iterable<E> {
private static class Node<E> { E value; Node<E> next;
public Node(E value, Node<E> next) { this.value = value; this.next = next; } }
Node<E> head = new Node<>(null, null); Node<E> tail = head; private int size;
private int capacity = Integer.MAX_VALUE;
{ tail.next = head; }
public LinkedListQueue(int capacity) { this.capacity = capacity; }
public LinkedListQueue() { }
@Override public boolean offer(E value) { if(isFull()) { return false; } Node<E> added = new Node<>(value, null); tail.next = added; tail = added; size++; return true; }
@Override public E pool() { if(isEmpty()) { return null; } Node<E> first = head.next; head.next = first.next; size--; if(first == tail){ tail = head; } return first.value; }
@Override public E peek() { if(isEmpty()) { return null; } return head.next.value; }
@Override public boolean isEmpty() { return head == tail;
}
@Override public boolean isFull() { return size == capacity; }
@Override public Iterator<E> iterator() { return new Iterator<E>() { Node<E> p = head.next; @Override public boolean hasNext() { return p != head; }
@Override public E next() { E value = p.value; p = p.next; return value; } }; } }
|
环形数组实现队列
好处
1、对比普通数组,起点和终点更为自由,不用考虑数据移动
2、“环”意味着不存在【越界】问题
3、数组性能更佳
4、环形数组比较适合实现有界队列,RingBuffer等
下标计算的方法:
例如,数组长度是5,当前位置是3,向前走2步,此时下标为(3 + 2)%5 = 0
即:(cur + step)%length
·cur当前指针位置
·step前进步数
·length数组长度
方式一(留位置)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
| public class ArrayQueue1<E> implements Queue<E>, Iterable<E>{
private final E[] array; private int head = 0; private int tail = 0;
@SuppressWarnings("all") public ArrayQueue1(int capacity) { array = (E[])new Object[capacity + 1]; }
@Override public boolean offer(E value) { if(isEmpty()) { return false; } array[tail] = value; tail = (tail + 1) % array.length; return true; }
@Override public E pool() { if(isEmpty()) { return null; } E value = array[head]; head = (head + 1) % array.length; return value; }
@Override public E peek() { if(isEmpty()) { return null; } return array[head]; }
@Override public boolean isEmpty() {
return head == tail; }
@Override public boolean isFull() { return (tail+1) % array.length == head; }
@Override public Iterator<E> iterator() { return new Iterator<E>() { int p = head; @Override public boolean hasNext() { return p != tail; }
@Override public E next() { E value = array[p]; p = (p+1) % array.length; return value; } }; } }
|
方式二(size变量控制)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
| private final E[] array; private int head = 0; private int tail = 0; private int size;
@SuppressWarnings("all") public ArrayQueue2(int capacity) { array = (E[])new Object[capacity]; }
@Override public boolean offer(E value) { if(isEmpty()) { return false; } array[tail] = value; tail = (tail + 1) % array.length; size++; return true; }
@Override public E pool() { if(isEmpty()) { return null; } E value = array[head]; head = (head + 1) % array.length; size--; return value; }
@Override public E peek() { if(isEmpty()) { return null; } return array[head]; }
@Override public boolean isEmpty() {
return size == 0; }
@Override public boolean isFull() { return size == array.length; }
@Override public Iterator<E> iterator() { return new Iterator<E>() { int p = head; int count = 0; @Override public boolean hasNext() { return count < size; }
@Override public E next() { E value = array[p]; p = (p+1) % array.length; count++; return value; } }; }
|
方法三(头尾指针移动)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
| private final E[] array; private int head; private int tail;
@SuppressWarnings("all") public ArrayQueue3(int capacity) {
capacity -= 1; capacity |=capacity>>1; capacity |=capacity>>2; capacity |=capacity>>8; capacity |=capacity>>16; capacity += 1; array = (E[])new Object[capacity]; }
@Override public boolean offer(E value) { if(isEmpty()) { return false; } array[tail & (array.length - 1)] = value; tail++; return true; }
@Override public E pool() { if(isEmpty()) { return null; } E value = array[head & (array.length - 1)]; head++; return value; }
@Override public E peek() { if(isEmpty()) { return null; } return array[head & (array.length - 1)]; }
@Override public boolean isEmpty() { return head == tail; }
@Override public boolean isFull() { return tail - head == array.length; }
@Override public Iterator<E> iterator() { return new Iterator<E>() { int p = head; @Override public boolean hasNext() { return p != tail; }
@Override public E next() { E value = array[p & (array.length - 1)]; p++; return value; } }; }
|