欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 能源 > 数据结构之队列

数据结构之队列

2025/6/10 10:33:44 来源:https://blog.csdn.net/weixin_41965831/article/details/148516669  浏览:    关键词:数据结构之队列

系列文章目录

数据结构之ArrayList-CSDN博客

数据结构之LinkedList-CSDN博客

数据结构之栈-CSDN博客


目录

系列文章目录

前言

一、队列和链表

二、队列的常用方法

三、队列的模拟实现

1. 使用双向链表实现队列

2. 使用环形数组实现队列

四、队列和栈

1. 使用两个队列模拟实现栈

2. 使用两个栈模拟实现队列


前言

本文介绍了队列的常用方法,分别使用双向链表和环形数组模拟实现队列,使用队列模拟实现栈,以及使用栈模拟实现队列。


一、队列和链表

队列是一种特殊的线性表,允许在一端进行数据的插入,另一端进行数据的删除。插入一端称为队尾,删除一端称为队头。

队列的底层是一个链表,Queue 是单链表的数据结构,Deque 是双端链表,LinkedList 既实现了Queue,也实现了 Deque,同时还实现了 List,因此 LinkedList 既可以实现队列,又可以实现栈;

如果使用单链表实现栈:

尾插法入栈的时间复杂度是 O(N),尾删出栈的时间复杂度也是 O(N);

头插法入栈的时间复杂度是 O(1),头删出栈的时间复杂度也是 O(1);

如果增加尾指针:

尾插法入栈的时间复杂度是 O(1),尾删出栈的时间复杂度还是 O(N);

如果使用双向链表实现栈:

头插法入栈,头删出栈,尾插法入栈,尾删出栈的时间复杂度都是 O(1);

因此栈的实现既可以是顺序栈,也可以是链式栈;

队列也可以使用环形数组进行实现。

二、队列的常用方法

offer(E e): boolean 元素入队;

poll(): E 元素出队;

peek(): E 查看队头元素;

size(): int 返回队列元素个数;

isEmpty(): boolean 判断队列是否为空;

三、队列的模拟实现

1. 使用双向链表实现队列

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(this.front == null){this.front = node;this.rear = node;}else{this.rear.next = node;node.prev = this.rear;this.rear = node;}this.usedSize++;}public ListNode poll(){if(this.front == null){return null;}ListNode ret = this.front;this.usedSize--;if(this.front == this.rear){this.front = null;this.rear = null;return ret;}this.front = this.front.next;this.front.prev = null;return ret;}public ListNode peek(){if(this.front == null){return null;}return this.front;}public int size(){return this.usedSize;}public boolean isEmpty(){return this.usedSize == 0;}
}

2. 使用环形数组实现队列

front 表示环形数组中第一个元素的下标;

rear 表示环形数组中能够存放元素的下标;

len 表示环形数组的长度;

如何识别空和满:

可以定义一个 usedSize,当 usedSize == len 时,数组满;

可以通过标记,满了就将标记置为 true;

可以浪费一个空间,当 rear + 1 == front 就是满;

如何解决从最后一个下标到 0 下标的问题:

rear = (rear + 1) % len 

front = (front + 1) % len

通过上述公式,可以保证 front 和 rear 从最后一个下标往下走一步达到 0 下标;

以下采用浪费一个空间的方式使用环形数组模拟实现队列:

class MyCircularQueue {private int[] queue;private int front;private int rear;public MyCircularQueue(int k) {this.queue = new int[k + 1];}public boolean enQueue(int value) {if(isFull()) return false;this.queue[this.rear] = value;this.rear = (this.rear + 1) % this.queue.length;return true;}public boolean deQueue() {if(isEmpty()) return false;this.front = (this.front + 1) % this.queue.length;return true;}public int Front() {if(isEmpty()) return -1;return this.queue[this.front];}public int Rear() {if(isEmpty()) return -1;return this.queue[(rear - 1 + this.queue.length) % this.queue.length];}public boolean isEmpty() {if(this.rear == this.front) {return true;}return false;}public boolean isFull() {if((this.rear + 1) % this.queue.length == this.front) {return true;}return false;}
}

四、队列和栈

1. 使用两个队列模拟实现栈

入栈:当两个队列都为空,元素先放在队列 1 中,当有一个不为空,放到不为空的队列中;

出栈:当两个队列都为空,返回 -1,当有一个队列不为空,将该队列的前 n - 1 个元素放到另一个队列,弹出该队列的最后一个元素并返回;

查看栈顶元素:当两个队列都为空,返回 -1,当一个队列不为空,将该队列的前 n - 1 个元素放到另一个队列,弹出该队列的最后一个元素并保存,将该元素也存到另一个队列,并返回保存的值;

判断栈是否为空:当两个队列都为空,返回 true,否则返回 false;

import java.util.*;public class QueueToStack {private Queue<Integer> q1;private Queue<Integer> q2;public QueueToStack() {q1 = new LinkedList<>();q2 = new LinkedList<>();}public void push(int x) {if(q1.isEmpty() && q2.isEmpty()){q1.offer(x);}else{if(!q1.isEmpty()){q1.offer(x);}else{q2.offer(x);}}}public int pop() {if(empty()) return -1;if(!q1.isEmpty()){int size = q1.size();while(--size > 0){int t = q1.poll();q2.offer(t);}return q1.poll();}else{int size = q2.size();while(--size > 0){int t = q2.poll();q1.offer(t);}return q2.poll();}}public int top() {if(empty()) return -1;int ret = 0;if(!q1.isEmpty()){int size = q1.size();while(--size > 0){int t = q1.poll();q2.offer(t);}ret = q1.poll();q2.offer(ret);return ret;}else{int size = q2.size();while(--size > 0){int t = q2.poll();q1.offer(t);}ret = q2.poll();q1.offer(ret);return ret;}}public boolean empty() {if(q1.isEmpty() && q2.isEmpty()){return true;}return false;}
}

2. 使用两个栈模拟实现队列

入队:放到第一个栈;

出队:如果队列为空,返回 -1,否则从第二个栈出,如果第二个栈为空,就将第一个栈的元素出栈,放到第二个栈,直到第一个栈为空,从第二个栈出;

查看队头元素:如果队列为空,返回 -1,否则查看第二个栈栈顶元素,如果第二个栈为空,就将第一个栈的元素出栈,放到第二个栈,直到第一个栈为空,查看第二个栈栈顶元素;

判断队列是否为空:如果两个栈都为空,返回 true,否则返回 false;

import java.util.*;public class StackToQueue {private Stack<Integer> stack1;private Stack<Integer> stack2;public StackToQueue() {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()){int t = stack1.pop();stack2.push(t);}}int ret = stack2.pop();return ret;}public int peek() {if(empty()) return -1;if(stack2.isEmpty()){while(!stack1.isEmpty()){int t = stack1.pop();stack2.push(t);}}int ret = stack2.peek();return ret;}public boolean empty() {if(stack1.isEmpty() && stack2.isEmpty()){return true;}return false;}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词