- - 队列
简单来说就是排队,只允许在一端进行插入,在另一端进行删除的线性表。
特性:先进先出
进行删除的那一端叫队头,进行插入的那一端叫队尾。
- - 队列的使用
public static void main(String[] args) {
Queue<Integer> queue = new LinkedList<>();
//Queue是一个接口,在实例化时必须实例化LinkedList的对象,因为LinkedList实现了Queue接口
queue.offer(1);//入队列
queue.offer(2);
queue.offer(3);
queue.offer(4);
queue.offer(5);
System.out.println(queue.size());//获取队列中有效元素的个数
System.out.println(queue.peek());//获取队头元素
queue.poll();//出队列
System.out.println(queue.poll());
if(queue.isEmpty()) {
System.out.println("空");
}else {
System.out.println(queue.size());
}
}
- - 通过双向链表来模拟实现队列
public class MyQueue {//通过双向链表实现队列
static class ListNode {//内部类
private int val;
private ListNode prev;
private ListNode next;
public ListNode(int val){
this.val = val;
}
}
private ListNode front;//队头
private ListNode rear;//队尾
private int usedSize;
public void offer(int x) {//头插入
ListNode node = new ListNode(x);
if(front == null) {//第一次插入
front = rear = node;
}else {
node.next = front;
front.prev = node;
front = node;
}
usedSize++;
}
//出队列 相当于删除最后一个节点
public int poll() {
if(front == null) {//无节点
return -1;
}
int ret = rear.val;
if(front == rear) {//一个节点
front = null;
rear = null;
usedSize--;
return ret;
}
//多个节点
rear = rear.prev;
rear.next = null;
usedSize--;
return ret;//返回删除的节点
}
public int peek() {//获取队头元素
if(front == null) {
return -1;
}
return front.val;
}
public int getUsedSize(){//获取队内有效元素的个数
return usedSize;
}
public boolean isEmpty() {
return usedSize == 0;
}
}
- - 循环队列
方法一:多出一个空间,便于判满和判空
class MyCircularQueue {
private int[] elem;
private int front;// 队头下标
private int rear;// 队尾下标
public MyCircularQueue(int k) {
this.elem = new int[k+1];//多出来的那一个是为了判满
}
public boolean enQueue(int value) {//入队列
if (isFull()) {
return false;
}
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 = (rear == 0) ?elem.length-1 : rear-1;//当rear不等于0时,rear已经+1了,尾巴的下标应该是rear-1,由入队列可知
return elem[index];
}
public boolean isEmpty() {
return front == rear;
}
public boolean isFull() {
if ((rear + 1) % elem.length == front) {
return true;
}
return false;
}
}
方法二:用一个boolean标记
class MyCircularQueue {
private int[] elements;
private int front;
private int rear;
private boolean isFull;//一开始是False
public MyCircularQueue(int k) {
elements = new int[k];
}
public boolean enQueue(int value) {
//如果已经满了
if(isFull()) {
return false;
}
elements[rear] = value;
rear = (rear + 1) % elements.length;
//刷新标志位
if(rear == front) {
isFull = true;//此时的话队列满足了isFull()方法
}
return true;
}
public boolean deQueue() {
//如果为空
if(isEmpty()) {
return false;
}
front = (front + 1) % elements.length;
//刷新标志位
isFull = false;
return true;
}
public int Front() {
if(isEmpty()) {
return -1;
}
return elements[front];
}
public int Rear() {
if(isEmpty()) {
return -1;
}
if(rear == 0)
return elements[elements.length - 1];
else
return elements[rear - 1];
}
public boolean isEmpty() {
return front == rear && !isFull;
}
public boolean isFull() {
return front == rear && isFull;
}
}
- - 双端队列
- - 用队列实现栈
一个队列无法实现栈,得靠两个
class MyStack {
private Queue<Integer> qu1;
private Queue<Integer> qu2;
public MyStack() {
qu1 = new LinkedList<>();
qu2 = new LinkedList<>();
}
// 入栈:入到不为空的队列中,如果都为空,入到qu1.
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() {
// 2个队列都为空的时候
if (empty()) {
return -1;
}
if (!qu1.isEmpty()) {
int size = qu1.size();
for (int i = 0; i < size - 1; i++) {
int tmp = qu1.poll();
qu2.offer(tmp);
}
return qu1.poll();//还剩的那一个就是栈的栈顶元素
} else {
int size = qu2.size();
for (int i = 0; i < size - 1; i++) {
int tmp = qu2.poll();
qu1.offer(tmp);
}
return qu2.poll();
}
}
public int top() {
if (empty()) {
return -1;
}
int tmp = -1;
if (!qu1.isEmpty()) {
int size = qu1.size();
for (int i = 0; i < size; i++) {
tmp = qu1.poll();
qu2.offer(tmp);
}
return tmp;
} else {
int size = qu2.size();
for (int i = 0; i < size; i++) {
tmp = qu2.poll();
qu1.offer(tmp);
}
return tmp;
}
}
public boolean empty() {
// 两个队列都为空,栈为空。
return qu1.isEmpty() && qu2.isEmpty();
}
}
- - 用栈实现队列
class MyQueue {
private Stack<Integer> stack1;
private Stack<Integer> stack2;
public MyQueue() {
stack1 = new Stack<>();// 实例化对象
stack2 = new Stack<>();
}
public void push(int x) {// 把每一个元素都入stack1
stack1.push(x);
}
public int pop() {
if(empty()){
return -1;
}
if (stack2.empty()) {
while (!stack1.empty()) {// 将stack1中的元素push到stack2中
stack2.push(stack1.pop());
}
}
return stack2.pop();// 从队列开头移除
}
public int peek() {
if(empty()){
return -1;
}
if(stack2.empty()){
while(!stack1.empty()){
stack2.push(stack1.pop());
}
}
return stack2.peek();
}
public boolean empty() {
return stack1.empty() && stack2.empty();
}
}