接口与类的继承关系:
双端队列
双端队列:两端都可以进行入队和出队操作的队列
Deque接口—>LinkedList(实现类)
- 公共方法:isEmpty() / size() / contains() …
- 当栈使用时:
- 压栈:push(e)
- 查看栈顶元素:peek()
- 弹出栈顶元素:pop()
- 当单向队列使用时:
- 插入队列:add(e)
- 查看队首元素:element()
- 取出队首元素:remove()
方法:
方法 | 解释 |
---|---|
addFirst(e) / ofterFirst(e) | 入队列(头部元素) |
addLast(e) / ofterLast(e) | 入队列(尾部元素) |
removeFirst() / pool()First | 出队列(头部元素) |
removeLast() / poolLast() | 出队列(尾部元素) |
getFirst() / peekFirst() | 取元素(不删除,头部元素) |
getLast() / peekLast() | 取元素(不删除,尾部元素) |
注:Deque接口·继承自Queue接口,Queue接口继承于Collection接口
循环队列
数组下标循环小技巧:
- 下标最后再往后(offset 小于 array.length): index = (index + offset) % array.length
- 下标最前再往前(offset 小于 array.length): index = (index + array.length - offset) % array.length
区分循环队列的空与满: 当 Q.rear = Q.front 时认为队空 当 Q.rear + 1 = Q.front 时认为队满
例:622. 设计循环队列(leetcode)
class MyCircularQueue {
private final int[] array;
private int size;
private int frontIndex;
private int rearIndex;
//循环队列的数组容量是k
public MyCircularQueue(int k) {
array = new int[k];
size = 0;
frontIndex = 0;
rearIndex = 0;
}
//把value插入循环队列尾部
//成功返回true 失败(容量满了)返回false
public boolean enQueue(int value) {
if(size == array.length) {
return false;
}
array[rearIndex] = value;
size++;
rearIndex++;
if (rearIndex == array.length) {
rearIndex = 0;
}
return true;
}
public boolean deQueue() {
//从循环队列队首删除一个元素
//成功返true 失败(队列为空)返回false
if(size == 0) {
return false;
}
size--;
frontIndex++;
if(frontIndex == array.length) {
frontIndex = 0;
}
return true;
}
//返回队首元素
//队列为空返回-1
public int Front() {
if(size == 0) {
return -1;
}
return array[frontIndex];
}
//返回队尾元素
//队列为空返回-1
public int Rear() {
if(size == 0) {
return -1;
}
if(rearIndex == 0) {
return array[array.length - 1];
} else
return array[rearIndex - 1];
}
public boolean isEmpty() {
return size == 0;
}
public boolean isFull() {
return size == array.length;
}
}
注1:站和队列都是一种特殊的线性结构,只是对插入/删除元素的方式做了限制
注2:栈表现出 FILO 的特点,队列表现出 FIFO 的特点(add / remove / element
没有特殊说明时,时间复杂度都是O(1))
注3:时间角度
- 栈:回溯(求迷宫的路径、括号匹配)、关于树形结构和图形结构的深度优先遍历都可以使用栈
- 队列:保证公平性(做消息传递,关于树形结构和图形结构的广度优先遍历可以使用队列)