文章目录
- 单端队列
- 单端队列操作:Queue实现
- 双端队列
- 双端队列操作:Deque实现
- 循环队列
- 循环队列手动实现
- 优先级队列
- Q 不断取最大礼物并开方
单端队列
普通队列为单端队列,先进先出(FIFO)
只能从尾部插入,头部取出元素
省流图:
单端队列操作:Queue实现
Queue<Integer> queue = new LinkedList<>();
// 添加元素到队列的尾部
queue.offer(1);
queue.offer(2);
// 获取并移除队列的头部元素
int head = queue.poll();
// 获取但不移除队列的头部元素
int peek = queue.peek();
// 判断队列是否为空
boolean isEmpty = queue.isEmpty();
// 获取队列的大小
int size = queue.size();
双端队列
单端队列升级版,允许在队头和队尾都进行元素的插入删除操作
双端队列操作:Deque实现
Deque<Integer> deque = new ArrayDeque<>();
// 添加元素到双端队列的尾部
deque.offerLast(1);
deque.offerLast(2);
// 添加元素到双端队列的头部
deque.offerFirst(0);
// 获取并移除双端队列的头部元素
int head = deque.pollFirst();
// 获取并移除双端队列的尾部元素
int tail = deque.pollLast();
// 获取但不移除双端队列的头部元素
int peekHead = deque.peekFirst();
// 获取但不移除双端队列的尾部元素
int peekTail = deque.peekLast();
// 判断双端队列是否为空
boolean isEmpty = deque.isEmpty();
// 获取双端队列的大小
int size = deque.size();
循环队列
循环队列(Circular Queue),也称为环形队列,是一种队列数据结构,它将队列的最后一个位置连接到队列的第一个位置,使其形成一个环。在循环队列中,队列的前端和后端都可以绕回到数组的起始位置,从而有效利用数组的空间。
循环队列具有以下特点:
- 固定大小:循环队列的大小是固定的,一旦创建后就不能改变。
- 环绕:当到达数组的末尾时,指针将绕回到数组的起始位置。
- 满队列和空队列的区别:为了区分队列为空还是满,通常保留一个数组位置不使用,或者使用一个额外的变量来记录队列的大小。
循环队列手动实现
public class CircularQueue {private int[] queue;private int front;private int rear;private int size;private int capacity;public CircularQueue(int capacity) {this.capacity = capacity; // 队列容量(一般大小固定)this.queue = new int[capacity];this.front = 0; // 前端索引this.rear = 0; // 后端索引this.size = 0; // 队列中元素个数}public boolean isFull() {return size == capacity;}public boolean isEmpty() {return size == 0;}// 入队public boolean enqueue(int item) {if (isFull()) {System.out.println("队列为空");return false;}queue[rear] = item;rear = (rear + 1) % capacity; // 后端指针往后移,循环队列要取余size++;return true;}// 出队public Integer dequeue() {if (isEmpty()) {System.out.println("队列为空");return null;}int item = queue[front];front = (front + 1) % capacity;size--;return item;}public void display() {if (isEmpty()) {System.out.println("队列为空");return;}for (int i = 0; i < size; i++) {System.out.print(queue[(front + i) % capacity] + " ");}System.out.println();}public static void main(String[] args) {CircularQueue cq = new CircularQueue(5);cq.enqueue(1);cq.enqueue(2);cq.display();cq.dequeue();cq.display();}
}
优先级队列
本质上是大/小根堆
,队列中元素会根据某种规则进行优先级排序
- 利用PriorityQueue,
比较器Comparator
中指定 比较/排序 规则
Q 不断取最大礼物并开方
2558. 从数量最多的堆取走礼物 - 力扣(LeetCode)
public long pickGifts(int[] gifts, int k) {// 队列从头最大到尾最小,降序排序PriorityQueue<Integer> pq = new PriorityQueue<>((o1, o2) -> o2 - o1);for (int i = 0; i < gifts.length; i++) {pq.offer(gifts[i]);}// 关键步骤:取出最大数,开方,再放进去,重复k次for (int i = 0; i < k; i++) {int max = pq.poll();pq.offer((int)Math.sqrt(max)); // 由于是优先级队列,再放入元素后会自动重新排序的}long res = 0;while (!pq.isEmpty()){res += pq.poll();}return res;
}