Queue接口
Queue用于模拟队列这种数据结构。队列通常是指“先进先出(FIFO)”的容器。队列的头部保存在队列中存放时间最长的元素,尾部保存存放时间最短的元素。新元素插入到队列的尾部,取出元素会返回队列头部的元素。通常,队列不允许随机访问队列中的元素。
如图可知,Queue继承于Collec,Queue下面又有Deque、PriorityQueue和ArrayDeque
Queue接口提供了三个方法,添加,移除和获取。每种方法提供了两种形式,抛出异常和提供返回值。
其中抛出移除的方法:添加add(E)、移除remove()/获取element()
提供返回值:添加offer(E)、移除poll()、获取peek()
Deque接口:双端队列
Queue与Deque提供的方法对应:
Queue | Deque |
---|---|
add(E) | addLast(E) |
offer(E) | offerLast(E) |
remove() | removeFirst() |
poll() | pollFirst() |
element() | getFirst() |
peek() | peekFirst() |
ArrayDeque相当于一个栈:
Stack | Deque |
---|---|
push(E) | addFirst(E) |
无 | offerFirst(E) |
pop() | removeFirst() |
无 | pollFirst() |
peek() | peekFirst() |
无 | getFirst() |
ArrayDeque
ArrayDeque相当于一个循环数组,双端数组
1.不允许存放null元素
2.head指向第一个有效元素位置,tail指向尾部第一个可以插入元素的空闲位置
3.提供了addFirst()、addLast()、removeFirst()、removeLast()方法
自定义ArrayDeque
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
public class MyArrayDeque<E> {
private E[] elements;
private int head; //永远指向循环数组的头
private int tail;//永远指向循环数组中下一个可添加元素的位置
private int size;//实际元素个数
private static int maxSize = 5;
public MyArrayDeque(){
this(5);
}
public MyArrayDeque(int capacity){
elements = (E[])new Object[capacity];
maxSize=capacity;
public void add(E value){
//默认队尾添加
if ((tail+1)%maxSize==head){
elements= Arrays.copyOf(elements,2*maxSize);
maxSize=elements.length;
}
// tail=(tail+1)%maxSize;
elements[tail]=value;
tail=(tail+1)%elements.length;
}
public E remove(){
//默认队头删除
if (tail==head){
//队列为空
throw new UnsupportedOperationException("队列为空");
}else{
E result = elements[head];
elements[head] = null;
head = (head+1)%maxSize;
return result;
}
}
public E get(){
return elements[head];
}
public String toString(){
StringBuilder strs = new StringBuilder();
for (int i=head;i!=tail;i=(i+1)%maxSize){
strs.append(elements[i]+" ");
}
return strs.toString();
}
}
ArrayDeque源码
public void addFirst(E e) {
if (e == null)
throw new NullPointerException();
elements[head = (head - 1) & (elements.length - 1)] = e;
if (head == tail)
doubleCapacity();
}
public void addLast(E e) {
if (e == null)
throw new NullPointerException();
elements[tail] = e;
if ( (tail = (tail + 1) & (elements.length - 1)) == head)
doubleCapacity();
}
public boolean offerFirst(E e) {
addFirst(e);
return true;
}
public boolean offerLast(E e) {
addLast(e);
return true;
}
public E removeFirst() {
E x = pollFirst();
if (x == null)
throw new NoSuchElementException();
return x;
}
public E removeLast() {
E x = pollLast();
if (x == null)
throw new NoSuchElementException();
return x;
}
public E pollFirst() {
int h = head;
@SuppressWarnings("unchecked")
E result = (E) elements[h];
// Element is null if deque empty
if (result == null)
return null;
elements[h] = null; // Must null out slot
head = (h + 1) & (elements.length - 1);
return result;
}
public E pollLast() {
int t = (tail - 1) & (elements.length - 1);
@SuppressWarnings("unchecked")
E result = (E) elements[t];
if (result == null)
return null;
elements[t] = null;
tail = t;
return result;
}
public E getFirst() {
@SuppressWarnings("unchecked")
E result = (E) elements[head];
if (result == null)
throw new NoSuchElementException();
return result;
}
public E getLast() {
@SuppressWarnings("unchecked")
E result = (E) elements[(tail - 1) & (elements.length - 1)];
if (result == null)
throw new NoSuchElementException();
return result;
}
public E peekFirst() {
// elements[head] is null if deque empty
return (E) elements[head];
}
@SuppressWarnings("unchecked")
public E peekLast() {
return (E) elements[(tail - 1) & (elements.length - 1)];
}
PriorityQueue
PriorityQueue是优先级队列,通常会建立小根堆;
priorityQueue默认为自然排序,或者通过提供的Comparator比较器去进行排序;
优先级队列从头获取元素是基于自然排序或者比较器排序的最小元素
priorityQueue举例:
自然排序示例:
Queue<Integer> intQueue = new PriorityQueue<>(5);
for(int i=0; i<5; i++){
intQueue.add((int)(Math.random() * 100));
}
for(Integer i: intQueue){
System.out.print(i+ " ");
}
System.out.println();
for(int i=0; i<5; i++){
System.out.println(intQueue.remove());
}
提供比较器示例:
class People{
private int id;
private String name;
public People(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "People{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
class IdComparator implements Comparator<People>{
@Override
public int compare(People o1, People o2) {
return 0;
}
}
public class TestDemo7 {
private static Comparator<People> idComparator = new Comparator<People>() {
@Override
public int compare(People o1, People o2) {
return o1.getId() - o2.getId();
}
};
private static Comparator com = new IdComparator();
public static void main(String[] args) {
//比较器使用示例 要求优先级队列按照People中的id属性去进行排序 id越小-》对象越小
Queue<People> peopleQueue = new PriorityQueue<>(5, idComparator);
for(int i=0; i<5; i++){
int id = (int)(Math.random() * 100);
peopleQueue.add(new People(id, "tulun"+id));
}
for(People p: peopleQueue){
System.out.print(p+" ");
}
System.out.println();
for(int i=0; i<5; i++){
System.out.println(peopleQueue.remove());
}
自定义priorityqueue
package collection;
import java.util.Arrays;
/**
* 自定义PriorityQueue
*
* add(e)/remove()/peek()/toString()
*/
class MyPriorityQueue<E extends Comparable<E>>{
private E[] queue; //存放元素的容器
private int size; //有效元素个数
private static int defaultCapacity = 5;
public MyPriorityQueue(){
this(5);
}
public MyPriorityQueue(int initCapacity){
queue = (E[]) new Comparable[initCapacity]; //
}
public void add(E value){
//添加一个元素到堆中 保持当前堆是小根堆
//判满 扩容
if(size == queue.length){
queue = Arrays.copyOf(queue, queue.length * 2);
}
//当前队列为空
if(size == 0){
queue[0] = value;
size++;
}else{
//当前队列不为空,需要调整当前队列为小根堆
adjust(size, value);
size++;
}
}
public void adjust(int index, E value){
while(index > 0){
int parantIndex = (index - 1 )/2;
if(queue[parantIndex].compareTo(value) > 0){
queue[index] = queue[parantIndex];//跟元素移动至index位置
index = parantIndex;//
}else{
break;
}
}
queue[index] = value;
}
public boolean remove(){
//空的队列
if(size == 0){
return false;
}
//当前队列只有一个元素
int index = --size;
if(index == 0){
queue[index] = null;
return true;
}
//当前队列存在多个元素 队头删除
queue[0] = null;
adjustDown(0, queue[index]);
return true;
}
public void adjustDown(int index, E value){
while(index < size/2){
int leftChild = index * 2 +1;
int rightChild = leftChild + 1;
E minNode = null;
int minIndex = 0;
if(leftChild < size){
minNode = queue[leftChild];
minIndex = leftChild;
}
//保证必须要有右孩子
if(rightChild < size && queue[leftChild].compareTo(queue[rightChild]) >= 0){
minNode = queue[rightChild];
minIndex = rightChild;
}
if(value.compareTo(minNode) < 0){
break;
}
queue[index] = minNode;
index = minIndex;
}
queue[index] = value;
}
public E peek(){
if(size == 0){
return null;
}
return queue[0];
}
@Override
public String toString(){
StringBuilder strs = new StringBuilder();
for(int i=0; i<size;i++){
strs.append(queue[i] + " ");
}
return strs.toString();
}
}
priorityqueue源码
public boolean offer(E e) {
if (e == null)
throw new NullPointerException();
modCount++;
int i = size;
if (i >= queue.length)
grow(i + 1);
size = i + 1;
if (i == 0)
queue[0] = e;
else
siftUp(i, e);
return true;
}
@SuppressWarnings("unchecked")
public E peek() {
return (size == 0) ? null : (E) queue[0];
}
private int indexOf(Object o) {
if (o != null) {
for (int i = 0; i < size; i++)
if (o.equals(queue[i]))
return i;
}
return -1;
}
public boolean remove(Object o) {
int i = indexOf(o);
if (i == -1)
return false;
else {
removeAt(i);
return true;
}
}
public E poll() {
if (size == 0)
return null;
int s = --size;
modCount++;
E result = (E) queue[0];
E x = (E) queue[s];
queue[s] = null;
if (s != 0)
siftDown(0, x);
return result;
}
private E removeAt(int i) {
// assert i >= 0 && i < size;
modCount++;
int s = --size;
if (s == i) // removed last element
queue[i] = null;
else {
E moved = (E) queue[s];
queue[s] = null;
siftDown(i, moved);
if (queue[i] == moved) {
siftUp(i, moved);
if (queue[i] != moved)
return moved;
}
}
return null;
}
private void siftUp(int k, E x) {
if (comparator != null)
siftUpUsingComparator(k, x);
else
siftUpComparable(k, x);
}
@SuppressWarnings("unchecked")
private void siftUpComparable(int k, E x) {
Comparable<? super E> key = (Comparable<? super E>) x;
while (k > 0) {
int parent = (k - 1) >>> 1;
Object e = queue[parent];
if (key.compareTo((E) e) >= 0)
break;
queue[k] = e;
k = parent;
}
queue[k] = key;
}
@SuppressWarnings("unchecked")
private void siftUpUsingComparator(int k, E x) {
while (k > 0) {
int parent = (k - 1) >>> 1;
Object e = queue[parent];
if (comparator.compare(x, (E) e) >= 0)
break;
queue[k] = e;
k = parent;
}
queue[k] = x;
}
private void siftDown(int k, E x) {
if (comparator != null)
siftDownUsingComparator(k, x);
else
siftDownComparable(k, x);
}
@SuppressWarnings("unchecked")
private void siftDownComparable(int k, E x) {
Comparable<? super E> key = (Comparable<? super E>)x;
int half = size >>> 1; // loop while a non-leaf
while (k < half) {
int child = (k << 1) + 1; // assume left child is least
Object c = queue[child];
int right = child + 1;
if (right < size &&
((Comparable<? super E>) c).compareTo((E) queue[right]) > 0)
c = queue[child = right];
if (key.compareTo((E) c) <= 0)
break;
queue[k] = c;
k = child;
}
queue[k] = key;
}
@SuppressWarnings("unchecked")
private void siftDownUsingComparator(int k, E x) {
int half = size >>> 1;
while (k < half) {
int child = (k << 1) + 1;
Object c = queue[child];
int right = child + 1;
if (right < size &&
comparator.compare((E) c, (E) queue[right]) > 0)
c = queue[child = right];
if (comparator.compare(x, (E) c) <= 0)
break;
queue[k] = c;
k = child;
}
queue[k] = x;
}