代码放开头,方便大家查阅
目录
一、实现代码
二、什么是队列
三、队列常见方法
入队push()
出队
四、Queue使用
Java自带的Queue
双端队列
五、习题
循环队列
用队列实现栈
用栈实现队列
一、实现代码
package demo2;
public class MyQueue {
class ListNode{
ListNode prev;
ListNode next;
int var;
public ListNode(int var) {
this.var = var;
}
}
ListNode first;
ListNode last;
int size=0;
public void offer(int val) {
ListNode node=new ListNode(val);
if(isEmpty()){
first=last=node;
}else {
last.next = node;
node.prev = last;
last = last.next;
}size++;
}
public int poll() {
int var=0;
if(first==null){
return -1;
}else if(first==last){
first=last=null;
}else {
var=first.var;
first.next.prev=null;
first=first.next;
}--size;
return var;
}
public int peek(){
if(isEmpty()){
return -1;
}
return first.var;
}
public boolean isEmpty() {
return 0==size;
}
}
二、什么是队列
简单来讲:先进先出的队伍!
假设第一个入队(push)的是1,第二个2 第三个3,那么先进先出的队伍,出来(pop)的是1,然后pop是2,pop是3。
三、队列常见方法
队列中有两种实现方式:一种是数组,一种是链表,
(Java中的队列也是采用链表实现的)这里我采用链表讲解。
入队push()
简单讲:多一个人排队!
入队都是往最后一个节点那里再加一个元素!
出队
简单来说:排队排到了,买完东西就走了(谁先排到,谁先走)
把第一次进入的元素蹦出来(删掉) 就行了
四、Queue使用
Java自带的Queue
在Java中,Queue是个接口,底层是通过链表实现的。
方法 | 功能 |
boolean offer(E e) | 入队列 |
E poll() | 出队列 |
peek() | 获取队头元素 |
int size() | 获取队列中有效元素个数 |
boolean isEmpty() | 检测队列是否为空 |
注意:
Queue是个接口,在实例化时必须实例化LinkedList的对象,因为LinkedList实现了Queue接口。
public static void main(String[] args) {
Queue<Integer> q = new LinkedList<>();
q.offer(1);
q.offer(2);
q.offer(3);
q.offer(4);
q.offer(5); // 从队尾入队列
System.out.println(q.size());
System.out.println(q.peek()); // 获取队头元素
q.poll();
System.out.println(q.poll()); // 从队头出队列,并将删除的元素返回
if(q.isEmpty()){
System.out.println("队列空");
}else{
System.out.println(q.size());
}
}
双端队列
双端队列(deque)是指允许两端都可以进行入队和出队操作的队列,deque 是 “double ended queue” 的简称。
那就说明元素可以从队头出队和入队,也可以从队尾出队和入队。
Deque是一个接口,使用时必须创建LinkedList的对象。 (如下图左下角LinkedList和右边Deque)
所以,我们如果要使用双端队列,应该写出如下代码:
Deque<Integer> queue1 = new ArrayDeque<>();//双端队列的线性实现
Deque<Integer> queue2 = new LinkedList<>();//双端队列的链式实现
五、习题
循环队列
思路如下:
如何循环?当下标为7时,如果再让last往下走last+1就是8就越界了,所以你需要有个方法,就是last=(last+1)%array.length,比如(7+1)%8=0,所以又是来一轮。
注意上图,比如这个last不是指6下标而是指7下标。
class MyCircularQueue {
int[] elem;
int first;
int last;
public MyCircularQueue(int k) {
elem = new int[k];
}
public boolean enQueue(int value) {
if (isFull()) {
return false;
}
elem[last] = value;
last = (last + 1) % elem.length;
return true;
}
public boolean deQueue() {
if (isEmpty()) {
return false;
}
first = (first+1)%elem.length;
return true;
}
public int Front() {
if (isEmpty()) {
return -1;
}
return elem[first];
}
public int Rear() {
if (isEmpty()) {
return -1;
}
int index=(last==0)?elem.length-1:last-1;
return elem[index];
}
public boolean isEmpty() {
return first == last;
}
public boolean isFull() {
return first == (last + 1) % elem.length;
}
}
注意的是,即使一模一样是上面的代码,也需要在构造函数的时候k+1,才不会报错。
用队列实现栈
思路如下:
一个队列肯定是实现不了栈的!为什么?
答:因为一个先进先出,一个先进后出,机制都不一样。所以需要两个队列。
怎么实现呢?
出栈:把一个队列的N-1个元素pop到空一个队列当中!当前队列剩下的一个元素就是我们需要“出栈”的元素!
入栈:把数据放到部位空的队列当中。
注意:第一次入栈时,两个队列都为空,那就放第一个。
import java.util.ArrayDeque;
class MyQueue {
public ArrayDeque<Integer> s1;
public ArrayDeque<Integer> s2;
public MyQueue() {
s1 = new ArrayDeque<>();
s2 = new ArrayDeque<>();
}
public void push(int x) {
s1.push(x);
}
public int pop() {
//2个栈都是空 意味着 队列为空
if(empty()) {
return -1;
}
if(s2.isEmpty()) {
while (!s1.isEmpty()) {
s2.push(s1.pop());
}
}
return s2.pop();
}
public int peek() {
if(empty()) {
return -1;
}
if(s2.isEmpty()) {
while (!s1.isEmpty()) {
s2.push(s1.pop());
}
}
return s2.peek();
}
public boolean empty() {
return s1.isEmpty() && s2.isEmpty();
}
}
用栈实现队列
思路如下:
入栈:放到第一个栈中
出栈:把第一个栈所有的元素全部放入第二个栈中,第二个栈里面的元素出栈入栈就已经是队列的排法了,如果第二个栈是空的,那么把第一个栈的都拿过来。
import java.util.ArrayDeque;
class MyQueue {
public ArrayDeque<Integer> s1;
public ArrayDeque<Integer> s2;
public MyQueue() {
s1 = new ArrayDeque<>();
s2 = new ArrayDeque<>();
}
public void push(int x) {
s1.push(x);
}
public int pop() {
//2个栈都是空 意味着 队列为空
if(empty()) {
return -1;
}
if(s2.isEmpty()) {
while (!s1.isEmpty()) {
s2.push(s1.pop());
}
}
return s2.pop();
}
public int peek() {
if(empty()) {
return -1;
}
if(s2.isEmpty()) {
while (!s1.isEmpty()) {
s2.push(s1.pop());
}
}
return s2.peek();
}
public boolean empty() {
return s1.isEmpty() && s2.isEmpty();
}