队列
引入
- 什么是队列?
- 在日常生活中,超市排队结账,就是一个简单的队列
- 排队,先到先排,排在前面 ,后到后排,排在后面,不能插队
- 先排的人,先结账,后排的人后结账
- 所以我们就可以看出 队列的特点
- 从一端入队,从一端出队
- **先入队的元素,先离开,后入队的元素,后离开 **
- 队列是一种只允许在一端进行插入操作,在另一端进行删除操作的先入先出的受限的线性表
队列的实现思路
- 和栈一样,队列有两种实现方式
- 数组实现的 顺序队列
- 链表实现的 链队列
普通数组队列
- 思路
- 创建一个类,类中有几个属性
- maxsize:定义了数组的长度
- front:指向队头元素,从0开始
- rear:指向队尾元素的后一个位置,从0开始
- 判断满员
- 当rear的值 > 数组最大元素下表 ,就代表已经满员了
- 即可换算为 rear == maxsize 时 ,满员,不能加人
- 判断是否为空
- 当 front == rear 时,代表现在没有人 ,不能取出(遍历)数组 ,例如:最初时
- 入队操作
- 当一个元素入队时,判断是否满员
- 若满员:则不能添加
- 若没有满员,则将rear所在的元素下表赋上值,赋完值之后,在rear++
- 出队操作
- 当要执行出队操作时,要先判断列队是否为空
- 为null:则不能出队
- 不为bull:则front++,即向前移动一位
- 遍历操作
- 当要执行遍历操作时,需要判断列队是否为null
- 为null:代表不能遍历
- 不为null:代表可以遍历 ,[ front , rear )
- 数组队列类
public class ArrayQueue {
private int maxSize;
private int front;
private int rear;
private int[] queue;
public ArrayQueue(int maxSize) {
this.maxSize = maxSize;
queue = new int[maxSize];
front = 0;
rear = 0;
}
public boolean isEmpty() {
return front == rear;
}
public boolean isFull() {
return rear == maxSize;
}
public void addEl(int n) {
if (!isFull()) {
queue[rear] = n;
rear++;
} else {
System.out.println("当前列队已满,不能加入");
}
}
public void removeEl() {
if (!isEmpty()) {
front++;
}else {
System.out.println("当前队列没有元素,不能移除");
}
}
public void showQueue() {
if (!isEmpty()) {
int temp = 0;
for (int i = front; i < rear; i++) {
temp++;
System.out.println("元素下表为"+i+"的元素的值为"+queue[i] );
}
}else {
System.out.println("当前队列没有元素");
}
}
public void showFirst(){
if (!isEmpty()){
System.out.println("第一个人是:"+queue[front]);
}else {
System.out.println("当前队列没有元素");
}
}
}
- 测试方法
ArrayQueue arrayQueue = new ArrayQueue(5);
boolean loop = true;
Scanner scanner = new Scanner(System.in);
while (loop){
System.out.println("==================================");
System.out.println("(a):进入队列");
System.out.println("(r):移除队列");
System.out.println("(l):队列列表");
System.out.println("(s):队列首元素");
System.out.println("(e):退出程序");
System.out.print("请选择你要的操作:");
char c = scanner.next().charAt(0);
switch (c){
case 'a':
System.out.print("请输入要入对的编号:");
Scanner s = new Scanner(System.in);
int i = s.nextInt();
arrayQueue.addEl(i);
break;
case 'r':
arrayQueue.removeEl();
break;
case 'l':
arrayQueue.showQueue();
break;
case 's':
arrayQueue.showFirst();
break;
case 'e':
loop = false;
break;
}
System.out.println();
}
循环数组队列
- 数组队列有一个很明显的缺点:数组只能使用一次,不能循环使用
- 那有没有一种办法能够使数组循环使用呢?这里就需要循环队列
- 循环队列:可以将数组想象成一个环,
- 思路
- 该数组中的指针 front 和 rear 有一个特点就是循环
- 当rear指向7时 ,再添加一个元素 ,元素添加至 7 处 ,rear 在 0 处
- 如果一直没有出队列 ,那么 front就在 0 处 ,rear == front
- 按照判定 ,rear == front 时 ,队列为 null ,显然不符合
- 所以,循环队列永远需要有一个 空闲元素 ,队列的最大长度 = 数组长度 - 1
- 创建一个类,类中有几个属性
- maxsize:定义了数组的**可储存的最大长度 **
- 数组的长度为 :maxsize + 1
- front:指向队头元素,从0开始
- rear:指向队尾元素的后一个位置,从0开始
- 判断是否为空
- 当 front == rear 时,代表现在没有人 ,不能取出(遍历)数组 ,例如:最初时
- 判断队列是否已满
- ( rear + 1 ) % length = front
- 计算循环列队有效元素长度
- ( rear + length - front )% length
- 遍历循环列队算法
- for (int i = front ; i <front+queueSize() ;i++ ){
** System.out.println("元素下表为"+( i % queue.length)+"的元素的值为"+queue[ i % queue.length]);**
** }**
- 添加操作
- 判断是否已满
- 满:return
- 未满:将值 赋给 现在 rear的坐标
- rear == maxsize
- rear = 0
- rear != 7
- rear++
- 删除操作
- 判断是否为null
- 为null : return
- 不为null :
- front == 7
- front = 0
- front != 7
- front++
- 遍历操作
- 判断是否为null
- 为null :return
- 不为null
- rear > front :
- 直接 [ front , rear)
- rear < front
- 1)[ front , 7 ]
- 2)[0 , rear)
public class LoopArrayQueue {
private int maxSize;
private int front;
private int rear;
private int[] queue;
public LoopArrayQueue(int maxSize) {
this.maxSize = maxSize;
queue = new int[maxSize+1];
front = 0;
rear = 0;
}
public boolean isEmpty() {
return front == rear;
}
public boolean isFull() {
return (( rear + 1 ) % queue.length) == front;
}
// 添加操作
public void addEl(int n) {
if (!isFull()) {
queue[rear] = n;
if (rear == maxSize){
rear = 0;
}else {
rear++;
}
} else {
System.out.println("当前列队已满,不能加入");
}
}
// 删除操作
public void removeEl() {
if (!isEmpty()) {
if (front == maxSize){
front = 0;
}else {
front++;
}
}else {
System.out.println("当前队列没有元素,不能移除");
}
}
// 遍历队列中的所有元素
public void showQueue() {
if (!isEmpty()) {
/*
普通思维方式遍历
if (rear > front){
for (int i = front; i < rear; i++) {
System.out.println("元素下表为"+i+"的元素的值为"+queue[i] );
}
}else {
for (int i = front; i < queue.length; i++) {
System.out.println("元素下表为"+i+"的元素的值为"+queue[i] );
}
for (int i = 0; i < rear; i++){
System.out.println("元素下表为"+i+"的元素的值为"+queue[i] );
}
}
*/
// 利用一个小算法,遍历
System.out.println("当前队列元素个数为:" +queueSize());
for (int i = front ; i <front+queueSize() ;i++ ){
System.out.println("元素下表为"+(i%queue.length)+"的元素的值为"+queue[i%queue.length]);
}
}else {
System.out.println("当前队列没有元素");
}
}
// 查看第一个元素
public void showFirst(){
if (!isEmpty()){
System.out.println("第一个人是:"+queue[front]);
}else {
System.out.println("当前队列没有元素");
}
}
// 计算队列中元素的个数
public int queueSize(){
return (rear+queue.length - front) % queue.length;
}
}
public static void main(String[] args) {
LoopArrayQueue arrayQueue = new LoopArrayQueue(5);
boolean loop = true;
Scanner scanner = new Scanner(System.in);
while (loop){
System.out.println("==================================11");
System.out.println("(a):进入队列");
System.out.println("(r):移除队列");
System.out.println("(l):队列列表");
System.out.println("(s):队列首元素");
System.out.println("(e):退出程序");
System.out.print("请选择你要的操作:");
char c = scanner.next().charAt(0);
switch (c){
case 'a':
System.out.print("请输入要入对的编号:");
Scanner s = new Scanner(System.in);
int i = s.nextInt();
arrayQueue.addEl(i);
break;
case 'r':
arrayQueue.removeEl();
break;
case 'l':
arrayQueue.showQueue();
break;
case 's':
arrayQueue.showFirst();
break;
case 'e':
loop = false;
break;
}
System.out.println();
}
}
春去秋来,岁岁平安
本文作者:发着呆看星
本文链接:https://www.cnblogs.com/fzdkx/p/17317365.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步