队列
概念
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(FirstIn First Out) 入队列:进行插入操作的一端称为队尾(Tail/Rear) 出队列:进行删除操作的一端称为队头(Head/Front)
接口关系
方法描述
方法 | 抛出异常 | 返回特殊值 |
---|---|---|
入队列 | add(e) | offer(e) |
出队列 | remeve() | poll() |
队首元素 | element() | peek() |
方法实现
class Node {
public int val;
public Node next;
public Node(int val) {
this.val = val;
}
}
public class MyQueue {
public Node first;
public Node last;
//入栈
public boolean offer(int val) {
Node node = new Node(val);
if(this.first == null) {
this.first = node;
this.last = node;
}else {
this.last.next = node;
this.last = node;
}
return true;
}
//判断栈是否为空
public boolean isEmpty() {
if(this.first == null && this.last == null) {
return true;
}
return false;
}
//出栈
public int poll() throws RuntimeException{
if(isEmpty()) {
throw new RuntimeException("队列为空");
}
int ret = this.first.val;
this.first = this.first.next;
return ret;
}
//得到队头元素
public int peek() {
if(isEmpty()) {
throw new RuntimeException("队列为空");
}
return this.first.val;
}
}
用栈实现队列
class MyQueue {
Stack<Integer> a;
Stack<Integer> b;
/** Initialize your data structure here. */
public MyQueue() {
a = new Stack<>();
b = new Stack<>();
}
/** Push element x to the back of queue. */
public void push(int x) {
a.push(x);
}
/** Removes the element from in front of queue and returns that element. */
public int pop() {
if(b.empty()) {
int size = a.size();
for(int i = 0; i < size; i++) {
b.push(a.pop());
}
}
return b.pop();
}
/** Get the front element. */
public int peek() {
if(b.empty()) {
int size = a.size();
for(int i = 0; i < size; i++) {
b.push(a.pop());
}
}
return b.peek();
}
/** Returns whether the queue is empty. */
public boolean empty() {
return a.empty() && b.empty();
}
}
循环队列
解决思路
抛出问题:队列是否可以用数组实现?
答案:可以的,如果把数组想成一个环,当数组满的时候将数据插入到数组头位置,这样就形成了循环队列。
问题1:front和rear相遇,到底是空还是满?
解决方法:
牺牲一个空间,来判断是否为满
判断当前rear的下一个是否为front
问题2:front和rear都会面临一个越界的问题?
解决方法:
加一个条件判断
当 (rear+1)%len == front 的时候,就要发生空间转换
代码实现
class MyCircularQueue {
public int[] arr;
public int rear; //队尾
public int front; //队首
public int len;
public MyCircularQueue(int k) {
arr = new int[k+1];
len = k+1;
}
public boolean enQueue(int value) {
if(isFull()) return false;
arr[rear%len] = value;
rear++;
return true;
}
public boolean deQueue() {
if(isEmpty()) return false;
front++;
return true;
}
public int Front() {
if(isEmpty()) return -1;
return arr[front%len];
}
public int Rear() {
if(isEmpty()) return -1;
return arr[(rear-1)%len];
}
public boolean isEmpty() {
return rear == front;
}
public boolean isFull() {
return (rear+1)%len == (front)%len;
}
}