文章目录
- 一、队列是什么?
- 二、模拟实现队列
- 三、模拟实现循环队列
- 四、用队列实现栈
- 五、用栈实现队列
一、队列是什么?
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾(Tail/Rear) 出队列:进行删除操作的一端称为队头(Head/Front)
队列是一种特殊的线性表,它只允许在表的前端进行删除操作,而在表的后端进行插入操作。
LinkedList类实现了Queue接口,因此我们可以把LinkedList当成Queue来用。
二、模拟实现队列
队列中既然可以存储元素,那底层肯定要有能够保存元素的空间,通过前面线性表的学习了解到常见的空间类型有两种:顺序结构 和 链式结构。同学们思考下:队列的实现使用顺序结构还是链式结构好?
因为队列是一种先进先出的数据结构,顺序表要想达到此目的,删除和取数据时间复杂度达到了O(n),那我们可不可以用单链表而且时间复杂度是O(1)呢?
public class MyQueue { static class ListNode { public int value; public ListNode next; public ListNode(int value) { this.value = value; } } public ListNode head; public ListNode tail; //入队列 public void offer(int data) { ListNode node = new ListNode(data); if(head == null) { head = node; tail = node; return; } tail.next = node; tail = node; } //出队列 public int poll() { if(isEmpty()) { return -1; } int ret = head.value; head = head.next; if(head == null) { tail = null; } return ret; } //查看队列第一个元素 public int peek() { if(isEmpty()) { return -1; } int ret = head.value; return ret; } //判断队列是否为空 public boolean isEmpty() { return size() == 0; } //获取队列大小 public int size() { ListNode cur = head; int count = 0; while (cur != null) { cur = cur.next; count++; } return count; }}
三、模拟实现循环队列
循环队列是把顺序队列首尾相连,把存储队列元素的表从逻辑上看成一个环,成为循环队列。
在实现循环队列时,我们主要面临的问题是,什么情况下队列为空,什么情况下队列为满,在判断满时:我们有两种方案,定义一个size变量,如果等于0为空,等于队列容量为满,这种过于简单,我们采用浪费一个空间的办法,如果head == tail队列为空,如果tail的下一个位置为head为满。
class MyCircularQueue { public int[] arr; public MyCircularQueue(int k) { arr = new int[k+1]; } public int front; public int rear; public boolean enQueue(int value) { if(isFull()) { return false; } arr[rear] = value; rear = (rear + 1) % arr.length; return true; } public boolean deQueue() { if(isEmpty()) { return false; } front = (front + 1) % arr.length; return true; } public int Front() { if(!isEmpty()) { return arr[front]; } return -1; } public int Rear() { if(!isEmpty()) { int ret = rear == 0 " /> import java.util.LinkedList;import java.util.Queue;class MyStack { public Queue<Integer> qu1; public Queue<Integer> qu2; public MyStack() { qu1 = new LinkedList<>(); qu2 = new LinkedList<>(); } public void push(int x) { if(empty()) { qu1.offer(x); return; } if(qu1.isEmpty()) { qu2.offer(x); }else { qu1.offer(x); } } public int pop() { if(empty()) { return -1; } if(qu1.isEmpty()) { int x = qu2.size(); for (int i = 0; i < x - 1; i++) { qu1.offer(qu2.poll()); } return qu2.poll(); }else { int x = qu1.size(); for (int i = 0; i < x - 1; i++) { qu2.offer(qu1.poll()); } return qu1.poll(); } } public int top() { if(empty()) { return -1; } if(qu1.isEmpty()) { int x = qu2.size(); for (int i = 0; i < x - 1; i++) { qu1.offer(qu2.poll()); } int ret = qu2.poll(); qu1.offer(ret); return ret; }else { int x = qu1.size(); for (int i = 0; i < x - 1; i++) { qu2.offer(qu1.poll()); } int ret = qu1.poll(); qu2.offer(ret); return ret; } } public boolean empty() { return qu1.isEmpty() && qu2.isEmpty(); }}
五、用栈实现队列
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):
实现 MyQueue 类:
void push(int x) 将元素 x 推到队列的末尾
int pop() 从队列的开头移除并返回元素
int peek() 返回队列开头的元素
boolean empty() 如果队列为空,返回 true ;否则,返回 false
import java.util.Stack;class MyQueue{ public Stack<Integer> s1; public Stack<Integer> s2; public MyQueue() { s1 = new Stack<>(); s2 = new Stack<>(); } public void push(int x) { s1.push(x); } public int pop() { if(empty()) { return -1; } if(!s2.empty()) { return s2.pop(); }else { while(!s1.empty()) { s2.push(s1.pop()); } return s2.pop(); } } public int peek() { if(empty()) { return -1; } if(!s2.empty()) { return s2.peek(); }else { while(!s1.empty()) { s2.push(s1.pop()); } return s2.peek(); } } public boolean empty() { return s1.empty() && s2.empty(); }}