什麼是隊列?
隊列是一種固定大小的有序清單,它的特點是先進先出。
隊列有四個重要參數,【頭】【尾】【最大長度】【資料區】
在 Java 中的聲明方式:
當隊列建構完成以後,隊尾和隊首同時指向 位址 1 ,當向隊列插入資料時,隊尾向後移動,直至隊尾等于 maxSize時 ((全文:隊首、隊尾初始值為 0),maxSize = 5) 隊列已滿,我們便無法再向隊列插入資料
每當我們取出一個資料,隊首就向後移動一個位址,直至 隊首等于隊尾,所有資料取完,隊列為空。
根據上面的分析,我們可以知道,當隊尾 = 隊首時 隊列為空,當 隊尾 = maxSize 時,隊列已滿。
這是一個傳統的隊列,每當我們取出一個資料,隊列的可用空間就會失去一個,也就是說,這個隊列隻能使用一次。
那麼如何讓隊列空間可以重複利用呢?
循環隊列它來了!循環隊列是通過一定的算法,将一個線性隊列看作一個環,使得這個隊列空間可以重複利用的資料結構。
循環隊列,了解上可以将它了解成一個環,但它實際還是一個線性隊列,隻是再傳統隊列的基礎之上通過算法,使它的空間可以重複利用。
在環形隊列中,我們無法再像傳統隊列那樣,使用隊尾 = maxSize 來判斷隊列是否已滿。
是以,為了能夠判斷隊列是否已經存儲滿,我們需要浪費掉一個空間來判斷是否已滿。而這個空間,始終是隊尾的後一個空間。而這個判斷條件就是,浪費掉的空間 取模 maxSize 是否等于隊首,隊尾的值,始終取 隊尾%maxSize
即 (rear+1)% 8 == front | rear = rear%8
為了了解,這裡做出幾個資料假設:
假設 隊首(front) 隊尾(rear)maxSize = 8
下表是填充資料不取出的情況
隊尾(rear) | 浪費掉的空間(rear+1)% maxSize | 隊首(front) | 隊列是否已滿(T/F) |
1 | F | ||
1 | 2 | F | |
2 | 3 | F | |
.... | .... | .... | .... |
7 | 0 ( 8 % 8) | T |
填充,并取出兩個資料即 隊首 = 2 (取出0,1兩個位址的資料後,隊首的位置)
隊尾(rear) | 浪費掉的空間(rear+1)% maxSize | 隊首(front) | 隊列是否已滿(T/F) |
7 | 2 | F | |
8 | 1 ( 8+1 = 9 % 8 ) | 2 | F |
1 | 2 (1+1 = 2 % 8) | 2 | T |
ok,我們總結一下,傳統隊列和循環隊列,空,滿時的條件
空 | 滿 | |
傳統隊列 | front = rear | rear = maxSize |
循環隊列 | front = rear | front = (rear+1)%maxSize |
在傳統隊列中,隊首和隊尾的取值最大為maxSize ,而循環隊列中,隊首和隊尾的取值都是在 %maxSize 進行一個循環 即(rear % 8 ,front%8)
最後:書寫不易,多多支援!附上代碼:
傳統隊列
package com.uxteam.data;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/*
* 隊列: 隊列是一種先進先出的線性表,他隻允許從尾部插入資料,頭部删除資料,通常由連結清單或數組實作
*
* */
public class ArrayQueue {
// 隊列的最大長度
private int maxSize;
// 隊列頭部位置
private int front;
// 隊列尾部位置
private int rear;
// 隊列資料存儲區域
private int[] data;
public ArrayQueue(int maxSize){
init(maxSize);
}
// 初始化隊列資料
private void init(int maxSize){
this.maxSize = maxSize;
this.front = 0;
this.rear = 0;
this.data = new int[maxSize];
}
/**
* 判斷隊列是否為空
* @return true / false
*/
// todo 判斷隊列是否為空 -- 完成
public boolean isEmpty(){
return rear - front == 0;
}
/***
* 判斷隊列是否已滿
* @return true / false
*/
// todo 判斷隊列是否已滿 -- 完成
public boolean isFull(){
return rear == maxSize;
}
// todo 向隊列插入元素 -- 完成
public void insert(int ele){
// 如果隊列已滿,抛出異常
if (isFull()){
throw new RuntimeException("隊列已滿");
}
this.data[rear++] = ele;
}
// todo 從隊列删除元素 -- 完成
public int remove(){
// 如果隊列是空,抛出異常
if (isEmpty()){
throw new RuntimeException("隊列為空");
}
return this.data[front++];
}
// todo 顯示隊列所有元素 -- 完成
public void list(){
List<Integer> collect = Arrays.stream(this.data).boxed().collect(Collectors.toList());
System.out.println(collect.subList(front,rear));
}
// todo 顯示隊列頭部元素 -- 完成
public int first(){
if (isEmpty()){
throw new RuntimeException("隊列為空");
}
return this.data[front];
}
}
循環隊列
package com.uxteam.data;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class CircleQuque {
/***
* 環形隊列最大容量
*/
private int maxSize;
/***
* 隊首位置
*/
private int front;
/***
* 隊尾位置
*/
private int rear;
/***
* 資料區
*/
private int[] data;
/***
* 隊列構造器
* @param maxSize 隊列最大容量
*/
public CircleQuque(int maxSize){
init(maxSize);
}
/***
* 初始化内部參數
* @param maxSize 隊列最大容量
*/
private void init(int maxSize){
this.maxSize = maxSize;
this.front = 0;
this.rear = 0;
this.data = new int[maxSize];
}
// todo 判斷隊列是否為空
/***
* 判斷隊列是否為空
* @return true / false
*/
public boolean isEmpty(){
return front == rear;
}
// todo 判斷隊列是否已滿
/***
* 判斷隊列是否已滿
* @return true / false
*/
public boolean isFull(){
return (rear+1)%maxSize == front;
}
// todo 向隊列添加元素
/***
* 向隊列添加元素
* @param ele 要添加的元素
*/
public void insert(int ele){
// 判斷隊列是否已滿
if (isFull()){
System.out.println("隊列已滿!");
return;
}
// 插入元素,隊尾後移
this.data[rear] = ele;
rear = (rear+1) % maxSize;
}
// todo 從隊列取出元素
/***
* 從隊列取出元素
* @return 取出的元素
*/
public int remove(){
// 判斷隊列是否為空
if (isEmpty()){
throw new RuntimeException("隊列為空");
}
// 傳回隊首資料,隊首後移
int remove = this.data[front];
front = (front+1) % maxSize;
return remove;
}
// todo 顯示隊列中所有元素
/***
* 顯示隊列中所有元素
*/
public void list(){
List<Integer> collect = Arrays.stream(this.data).boxed().collect(Collectors.toList());
if (rear < front){
System.out.println(collect.subList(0,rear));
System.out.println(collect.subList(front,maxSize));
}else {
System.out.println(collect.subList(front,rear));
}
}
// todo 顯示隊列首元素
/***
* 顯示隊列首元素
* @return 隊列首元素
*/
public int first(){
// 判斷隊列是否為空
if (isEmpty()){
throw new RuntimeException("隊列為空");
}
return this.data[front];
}
}