队列
队列概念
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出的特点。
入队列:进行插入操作的一端称为队尾。
出队列:进行删除操作的一端称为队头。
基本用法
Queue<Integer> queue=new LinkedList<>();
queue.add(1);//插入元素
queue.offer(2);///插入元素【常用】
System.out.println(queue.element());//获取队头元素 1
System.out.println(queue.peek());//获取队头元素 1【常用】
System.out.println(queue.poll());//出元素 1 【常用】
System.out.println(queue.remove());//出元素 2
双端队列
概念
双端队列(deque)是指允许两端都可以进行入队和出队操作的队列。
基本用法
Deque<Integer> queue2=new LinkedList<>();
queue2.offer(1);//默认从队尾入队
queue2.offerFirst(2);
System.out.println(queue2.peek());
🎈LinkedList,可以当做普通的队列,可以当做双端队列,可以当做双向链表,也可以当做栈。
用单链表实现队列
class Node{
public int val;
public Node next;
public Node(int val) {
this.val=val;
}
}
public class LiMyQueue {
public Node head;
public Node last;
//尾插法
public void offer(int val) {
Node node= new Node(val);
if(head==null) {
head=node;
last=node;
}else {
last.next=node;
last=last.next;
}
}
//出队
public int poll() {
if(isEmpty()) {
throw new RuntimeException("队列为空");
}
int oldVal=head.val;
this.head=head.next;
return oldVal;
}
public boolean isEmpty() {
return this.head==null;
}
public int peek() {
if(isEmpty()) {
throw new RuntimeException("队列为空");
}
return head.val;
}
}
循环队列
如果使用数组实现队列。
循环队列判断是空还是满
使用usedSize
使用usedSize和数组长度进行比较,判断满或者空。
使用标志位
浪费一个空间
实现循环队列
//以下判空判满是使用浪费一个空间的方法
public class LiMyCircularQueue {
public int[] elem;
public int front;//队头下标
public int rear;//队尾下标
public LiMyCircularQueue(int k) {
this.elem=new int[k];
}
//入队
public boolean enQueue(int value) {
if(isFull()) {
return false;
}
this.elem[rear]=value;
rear=(rear+1)%elem.length;
return true;
}
//出队
public boolean deQueue() {
if(isEmpty()) {
return false;
}
front=(front+1)%elem.length;
return true;
}
//得到队头元素
public int front() {
if(isEmpty()) {
return -1;
}
return elem[front];
}
//得到队尾元素
public int rear() {
if(isEmpty()) {
return -1;
}
int index=-1;
if(rear==0) {
index=elem.length-1;
}else {
index=rear-1;
}
return elem[index];
}
//判空
public boolean isEmpty() {
return front==rear;
}
//判满
public boolean isFull() {
//rear的下一个是front说明满了
if((rear+1)%elem.length==front ) {
return true;
}
return false;
}
}
习题
用队列实现栈
入栈的时候,入到不为空的队列,刚开始都为空,指定入到一个队列。
出栈的时候,找到不为空的队列,出size-1个元素到另一个队列,剩下的这个元素就是出栈的元素。
private Queue<Integer> qu1;
private Queue<Integer> qu2;
public MyStack() {
qu1=new LinkedList<>();
qu2=new LinkedList<>();
}
public void push(int x) {
if(!qu1.isEmpty()){
qu1.offer(x);
}else if(!qu2.isEmpty()){
qu2.offer(x);
}else{
qu1.offer(x);
}
}
public int pop() {
if(empty()) return -1;
if(!qu1.isEmpty()){
int size=qu1.size();
for(int i=0;i<size-1;i++){
int val=qu1.poll();
qu2.offer(val);
}
return qu1.poll();
}
if(!qu2.isEmpty()){
int size=qu2.size();
for(int i=0;i<size-1;i++){
int val=qu2.poll();
qu1.offer(val);
}
return qu2.poll();
}
return -1;
}
public int top() {
if(empty()) return -1;
if(!qu1.isEmpty()){
int val=-1;
int size=qu1.size();
for(int i=0;i<size;i++){
val=qu1.poll();
qu2.offer(val);
}
return val;
}
if(!qu2.isEmpty()){
int val=-1;
int size=qu2.size();
for(int i=0;i<size;i++){
val=qu2.poll();
qu1.offer(val);
}
return val;
}
return -1;
}
public boolean empty() {
return qu1.isEmpty() && qu2.isEmpty();
}
用栈实现队列
入队的时候,统一入到第一个栈
出栈的时候,统一出第二个栈里面的元素,如果第二个栈为空,吧第一个栈的元素全部到过来,然后出栈顶元素
class MyQueue {
public Stack<Integer> stack1;
public Stack<Integer> stack2;
public MyQueue() {
stack1=new Stack<>();
stack2=new Stack<>();
}
public void push(int x) {
stack1.push(x);
}
public int pop() {
if(empty()) return -1;
if(stack2.isEmpty()){
while(!stack1.isEmpty()){
stack2.push(stack1.pop());
}
}
return stack2.pop();
}
public int peek() {
if(empty()) return -1;
if(stack2.isEmpty()){
while(!stack1.isEmpty()){
stack2.push(stack1.pop());
}
}
return stack2.peek();
}
public boolean empty() {
return stack1.isEmpty() && stack2.isEmpty();
}
}
设计循环队列
class MyCircularQueue {
public int[] elem;
public int front;//对头下标
public int rear;//队尾下标
public MyCircularQueue(int k){
this.elem=new int[k+1];
}
//入队
public boolean enQueue(int value){
if(isFull()) return false;
this.elem[rear]=value;
rear=(rear+1) % elem.length;
return true;
}
//出队
public boolean deQueue(){
if(isEmpty()){
return false;
}
front=(front+1)%elem.length;
return true;
}
//得到队头元素
public int Front(){
if(isEmpty()){
return -1;
}
return elem[front];
}
//得到队尾元素
public int Rear(){
if(isEmpty()){
return -1;
}
int index=-1;
if(rear==0){
index=elem.length-1;
}else{
index=rear-1;
}
return elem[index];
}
public boolean isFull(){
//rear的下一个是front
if((rear+1) % elem.length==front){
return true;
}
return false;
}
public boolean isEmpty(){
return front==rear;
}
}