队列与栈
队列
队列特点
队列是先进先出的数据结构,类似于排队
内部实现
直接用 java 内部的实现,其实内部就是双向链表 LinkedList,常数操作慢
java
public static class Queue1 {
// java中的双向链表LinkedList
// 单向链表就足够了
public Queue<Integer> queue = new LinkedList<>();
// 调用任何方法之前,先调用这个方法来判断队列内是否有东西
public boolean isEmpty() {
return queue.isEmpty();
}
// 向队列中加入num,加到尾巴
public void offer(int num) {
queue.offer(num);
}
// 从队列拿,从头拿
public int poll() {
return queue.poll();
}
// 返回队列头的元素但是不弹出
public int peek() {
return queue.peek();
}
// 返回目前队列里有几个数
public int size() {
return queue.size();
}
}数组实现
实际刷题时更常见的写法,常数时间好
如果可以确定加入操作的总次数不超过 n,那么可以用
一般笔试、面试都会有一个明确数据量,所以这是最常用的方式
采用双指针 l 和 r 操作元素,左闭右开 [ l , r ),l 指向队头,r 指向队尾的下一个位置
java
public static class Queue2 {
public int[] queue;
public int l;
public int r;
// 加入操作的总次数上限是多少,一定要明确
public Queue2(int n) {
queue = new int[n];
l = 0;
r = 0;
}
// 调用任何方法之前,先调用这个方法来判断队列内是否有东西
public boolean isEmpty() {
return l == r;
}
public void offer(int num) {
queue[r++] = num;
}
public int poll() {
return queue[l++];
}
public int head() {
return queue[l];
}
// l...r-1 r
// [l..r)
public int tail() {
return queue[r - 1];
}
public int size() {
return r - l;
}
}循环队列
题目链接:https://leetcode.cn/problems/design-circular-queue/
利用双指针 l 和 r 操作元素(指向索引位置),如果到达末尾,就跳回 0,复用之前的位置实现循环利用
java
class MyCircularQueue {
public int[] queue;
public int l, r, size, limit;
// 同时在队列里的数字个数,不要超过k
public MyCircularQueue(int k) {
queue = new int[k];
l = r = size = 0;
limit = k;
}
// 如果队列满了,什么也不做,返回false
// 如果队列没满,加入value,返回true
public boolean enQueue(int value) {
if (isFull()) {
return false;
} else {
queue[r] = value;
// 如果 r 到了末尾,跳回 0,否则 r++
r = r == limit - 1 ? 0 : (r + 1);
size++;
return true;
}
}
// 如果队列空了,什么也不做,返回false
// 如果队列没空,弹出头部的数字,返回true
public boolean deQueue() {
if (isEmpty()) {
return false;
} else {
// 如果 l 到了末尾,跳回 0,否则 l++
l = l == limit - 1 ? 0 : (l + 1);
size--;
return true;
}
}
// 返回队列头部的数字(不弹出),如果没有数返回 -1
public int Front() {
if (isEmpty()) {
return -1;
} else {
return queue[l];
}
}
public int Rear() {
if (isEmpty()) {
return -1;
} else {
// 在入队后 r++,求队尾元素需要反推一个位置
int last = r == 0 ? (limit - 1) : (r - 1);
return queue[last];
}
}
public boolean isEmpty() {
return size == 0;
}
public boolean isFull() {
return size == limit;
}
}栈
栈特点
栈是后进先出的数据结构,类似于弹夹
内部实现
java
// 直接用java内部的实现
// 其实就是动态数组,不过常数时间并不好
public static class Stack1 {
public Stack<Integer> stack = new Stack<>();
// 调用任何方法之前,先调用这个方法来判断栈内是否有东西
public boolean isEmpty() {
return stack.isEmpty();
}
public void push(int num) {
stack.push(num);
}
public int pop() {
return stack.pop();
}
public int peek() {
return stack.peek();
}
public int size() {
return stack.size();
}
}数组实现
实际刷题时更常见的写法,常数时间好
如果可以保证同时在栈里的元素个数不超过 n,那么可以用
也就是发生弹出操作之后,空间可以复用
一般笔试、面试都会有一个明确数据量,所以这是最常用的方式
size 充当计数的作用,同时也是指针,size 始终指向栈顶元素的下一个位置
java
public static class Stack2 {
public int[] stack;
public int size;
// 同时在栈里的元素个数不会超过n
public Stack2(int n) {
stack = new int[n];
size = 0;
}
// 调用任何方法之前,先调用这个方法来判断栈内是否有东西
public boolean isEmpty() {
return size == 0;
}
public void push(int num) {
stack[size++] = num;
}
/*
--size
(1)弹出元素,size 先减一
(2)size 减一后,size --> size - 1,而栈顶元素的下表索引是 size - 1,弹出栈顶元素
*/
public int pop() {
return stack[--size];
}
public int peek() {
return stack[size - 1];
}
public int size() {
return size;
}
}