Java基礎(chǔ)之?dāng)?shù)組模擬循環(huán)隊列
一、隊列簡介
隊列是一個有序列表,遵循“先入先出”的原則,即先存入隊列的數(shù)據(jù)要先取出,后存入的數(shù)據(jù)后取出。
隊列有兩種存儲表示,順序表示和鏈?zhǔn)奖硎?。順序表示可以用?shù)組來實現(xiàn)。
二、數(shù)組模擬隊列
用數(shù)組模擬隊列時,設(shè)兩個值front=0,rear=0。front表示隊列首部第一個數(shù)據(jù)所在位置,rear表示尾部最后一個數(shù)據(jù)的下一個位置。
將數(shù)據(jù)插入數(shù)組隊列時(入隊),從尾部進(jìn)行插入,即array[rear] = value,同時rear后移,rear++。取出數(shù)據(jù)時(出隊),從頭部取出數(shù)據(jù),value = array[front],同時front后移front++。
當(dāng)front=0,rear=maxSize(數(shù)組的最大長度),隊列滿,不能再存入數(shù)據(jù)。
這時如果執(zhí)行出隊操作,又有空間可以存儲,但繼續(xù)插入數(shù)據(jù),會出現(xiàn)溢出現(xiàn)象,即因數(shù)組越界而導(dǎo)致程序非法操作錯誤。而實際上空間并未占滿,所以稱這種現(xiàn)象為“假溢出”。這是由“隊尾入隊,隊頭出隊”的限制操作所造成的。
如何解決“假溢出”的問題呢?
答案就是循環(huán)隊列。
三、數(shù)組模擬循環(huán)隊列
將順序隊列變?yōu)橐粋€環(huán)狀空間,front、rear和隊列元素之間的關(guān)系不變,只是在循環(huán)隊列中,front、rear依次后移加1的操作可用“?!边\(yùn)算來實現(xiàn)。
通過取模,front、rear就可以在順序表空間內(nèi)以頭尾銜接的方式“循環(huán)”移動。
元素出隊后,front = (front+1)%maxSize ;
元素入隊后,rear = (rear+1)%maxSize 。
(maxSize為數(shù)組隊列的最大長度)
例如,隊列最大長度為4,當(dāng)rear=3時,存入數(shù)據(jù),array[3]=value,rear后移一位,如果沒有取模運(yùn)算,則rear=4,這時繼續(xù)插入數(shù)據(jù),array[4]越界。
如果進(jìn)行取模運(yùn)算,rear = (rear+1)%maxSize ,這時rear=0,rear又重新回到了0的位置。這樣的運(yùn)算,使得rear的值在0、1、2、3之間循環(huán)。
front的值同理。
寫了這么多字,感覺還不如看代碼來得更容易理解一點(diǎn)。
四、代碼實現(xiàn)
數(shù)組模擬循環(huán)隊列
package com.ArrayQueue;
import java.util.Scanner;
public class CircleArrayQueueDemo {
public static void main(String args[]){
int maxSize = 4;
CircleArrayQueue queue = new CircleArrayQueue(maxSize);
Scanner scanner = new Scanner(System.in);
char key;
boolean loop = true;
while (loop) {
//根據(jù)輸入的不同字母,進(jìn)行對應(yīng)的操作
System.out.println("a(add):添加一個數(shù)據(jù)");
System.out.println("g(get):取出一個數(shù)據(jù)");
System.out.println("h(head):展示頭部數(shù)據(jù)");
System.out.println("s(show):展示所有數(shù)據(jù)");
System.out.println("q(quit):退出程序");
//因為判滿條件的緣故,隊列的最大容量實為maxSize-1
System.out.printf("(隊列的最大容量為:%d)\n",maxSize-1);
key = scanner.next().charAt(0);//接收一個字符
try {
switch (key) {
case 'a':
System.out.println("請輸入一個數(shù):");
int value = scanner.nextInt();
queue.addQueue(value);
System.out.println("數(shù)據(jù)添加成功。");
break;
case 'g':
System.out.printf("取出的數(shù)據(jù)為:%d\n", queue.getQueue());
break;
case 'h':
queue.headQueue();
break;
case 's':
queue.showQueue();
break;
case 'q':
scanner.close();
loop = false;
System.out.println("程序已退出。");
break;
default:
break;
}
} catch (RuntimeException e) {
System.out.println(e.getMessage());
}
}
}
}
/**
* 隊列的順序表示
* 數(shù)組模擬循環(huán)隊列
*/
class CircleArrayQueue{
private int maxSize;
private int front;//指向頭元素所在位置
private int rear;//指向尾元素所在位置的下一個位置
private int arr[];//存放數(shù)據(jù)的數(shù)組
//構(gòu)造器,傳入數(shù)組最大容量值
public CircleArrayQueue(int size){
maxSize = size;
front = 0;
rear = 0;
//雖然數(shù)組最大容量為maxSize,但實際用于存儲的只有maxSize-1
arr = new int[maxSize];
}
//判空條件:front == rear
public boolean isEmpty(){
return front == rear;
}
//判滿條件:(rear+1)%maxSize == front
public boolean isFull(){
return (rear+1)%maxSize == front;
}
//添加數(shù)據(jù),入隊
public void addQueue(int n){
//判滿
checkFull();
arr[rear] = n;
rear = (rear+1)%maxSize;
}
//取出數(shù)據(jù),出隊
public int getQueue(){
//判空
checkEmpty();
int value = arr[front];
front = (front+1)%maxSize;
return value;
}
//隊列中的有效值個數(shù)
public int size(){
return (rear-front+maxSize)%maxSize;
}
//展示隊列的所有數(shù)據(jù)
public void showQueue(){
//判空
checkEmpty();
for(int i=front;i<front+size();i++){
System.out.printf("arr[%d]=%d\n",i%maxSize,arr[i%maxSize]);
}
System.out.printf("當(dāng)前front=%d,rear=%d\n",front,rear);
}
//展示位于隊列頭部的元素值,不改變front的指向
public void headQueue(){
//判空
checkEmpty();
System.out.printf("頭部數(shù)據(jù)是:%d\n",arr[front]);
}
//檢測出隊列為空時,打印當(dāng)前front,rear的值,拋出異常
public void checkEmpty(){
if (isEmpty()) {
System.out.printf("當(dāng)前front=%d,rear=%d\n",front,rear);
throw new RuntimeException("隊列為空,不能取數(shù)據(jù)");
}
}
//檢測出隊列滿時,打印當(dāng)前front,rear的值,拋出異常
public void checkFull(){
if(isFull()){
System.out.printf("當(dāng)前front=%d,rear=%d\n",front,rear);
throw new RuntimeException("隊列已滿,不能添加數(shù)據(jù)");
}
}
}
五、運(yùn)行結(jié)果




到此這篇關(guān)于Java基礎(chǔ)之?dāng)?shù)組模擬循環(huán)隊列的文章就介紹到這了,更多相關(guān)Java數(shù)組模擬循環(huán)隊列內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java多線程之循環(huán)柵欄技術(shù)CyclicBarrier使用探索
這篇文章主要介紹了Java多線程之循環(huán)柵欄技術(shù)CyclicBarrier,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪<BR>2024-01-01
mybatis中如何傳遞單個String類型的參數(shù)
這篇文章主要介紹了mybatis中如何傳遞單個String類型的參數(shù),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11
SpringCloud容器化服務(wù)發(fā)現(xiàn)及注冊實現(xiàn)方法解析
這篇文章主要介紹了SpringCloud容器化服務(wù)發(fā)現(xiàn)及注冊實現(xiàn)方法解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-08-08

