Java基礎(chǔ)之?dāng)?shù)組模擬循環(huán)隊(duì)列
一、隊(duì)列簡(jiǎn)介
隊(duì)列是一個(gè)有序列表,遵循“先入先出”的原則,即先存入隊(duì)列的數(shù)據(jù)要先取出,后存入的數(shù)據(jù)后取出。
隊(duì)列有兩種存儲(chǔ)表示,順序表示和鏈?zhǔn)奖硎?。順序表示可以用?shù)組來(lái)實(shí)現(xiàn)。
二、數(shù)組模擬隊(duì)列
用數(shù)組模擬隊(duì)列時(shí),設(shè)兩個(gè)值front=0,rear=0。front表示隊(duì)列首部第一個(gè)數(shù)據(jù)所在位置,rear表示尾部最后一個(gè)數(shù)據(jù)的下一個(gè)位置。
將數(shù)據(jù)插入數(shù)組隊(duì)列時(shí)(入隊(duì)),從尾部進(jìn)行插入,即array[rear] = value,同時(shí)rear后移,rear++。取出數(shù)據(jù)時(shí)(出隊(duì)),從頭部取出數(shù)據(jù),value = array[front],同時(shí)front后移front++。
當(dāng)front=0,rear=maxSize(數(shù)組的最大長(zhǎng)度),隊(duì)列滿,不能再存入數(shù)據(jù)。
這時(shí)如果執(zhí)行出隊(duì)操作,又有空間可以存儲(chǔ),但繼續(xù)插入數(shù)據(jù),會(huì)出現(xiàn)溢出現(xiàn)象,即因數(shù)組越界而導(dǎo)致程序非法操作錯(cuò)誤。而實(shí)際上空間并未占滿,所以稱這種現(xiàn)象為“假溢出”。這是由“隊(duì)尾入隊(duì),隊(duì)頭出隊(duì)”的限制操作所造成的。
如何解決“假溢出”的問(wèn)題呢?
答案就是循環(huán)隊(duì)列。
三、數(shù)組模擬循環(huán)隊(duì)列
將順序隊(duì)列變?yōu)橐粋€(gè)環(huán)狀空間,front、rear和隊(duì)列元素之間的關(guān)系不變,只是在循環(huán)隊(duì)列中,front、rear依次后移加1的操作可用“?!边\(yùn)算來(lái)實(shí)現(xiàn)。
通過(guò)取模,front、rear就可以在順序表空間內(nèi)以頭尾銜接的方式“循環(huán)”移動(dòng)。
元素出隊(duì)后,front = (front+1)%maxSize ;
元素入隊(duì)后,rear = (rear+1)%maxSize 。
(maxSize為數(shù)組隊(duì)列的最大長(zhǎng)度)
例如,隊(duì)列最大長(zhǎng)度為4,當(dāng)rear=3時(shí),存入數(shù)據(jù),array[3]=value,rear后移一位,如果沒(méi)有取模運(yùn)算,則rear=4,這時(shí)繼續(xù)插入數(shù)據(jù),array[4]越界。
如果進(jìn)行取模運(yùn)算,rear = (rear+1)%maxSize ,這時(shí)rear=0,rear又重新回到了0的位置。這樣的運(yùn)算,使得rear的值在0、1、2、3之間循環(huán)。
front的值同理。
寫了這么多字,感覺(jué)還不如看代碼來(lái)得更容易理解一點(diǎn)。
四、代碼實(shí)現(xiàn)
數(shù)組模擬循環(huán)隊(duì)列
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)行對(duì)應(yīng)的操作 System.out.println("a(add):添加一個(gè)數(shù)據(jù)"); System.out.println("g(get):取出一個(gè)數(shù)據(jù)"); System.out.println("h(head):展示頭部數(shù)據(jù)"); System.out.println("s(show):展示所有數(shù)據(jù)"); System.out.println("q(quit):退出程序"); //因?yàn)榕袧M條件的緣故,隊(duì)列的最大容量實(shí)為maxSize-1 System.out.printf("(隊(duì)列的最大容量為:%d)\n",maxSize-1); key = scanner.next().charAt(0);//接收一個(gè)字符 try { switch (key) { case 'a': System.out.println("請(qǐng)輸入一個(gè)數(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()); } } } } /** * 隊(duì)列的順序表示 * 數(shù)組模擬循環(huán)隊(duì)列 */ class CircleArrayQueue{ private int maxSize; private int front;//指向頭元素所在位置 private int rear;//指向尾元素所在位置的下一個(gè)位置 private int arr[];//存放數(shù)據(jù)的數(shù)組 //構(gòu)造器,傳入數(shù)組最大容量值 public CircleArrayQueue(int size){ maxSize = size; front = 0; rear = 0; //雖然數(shù)組最大容量為maxSize,但實(shí)際用于存儲(chǔ)的只有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ù),入隊(duì) public void addQueue(int n){ //判滿 checkFull(); arr[rear] = n; rear = (rear+1)%maxSize; } //取出數(shù)據(jù),出隊(duì) public int getQueue(){ //判空 checkEmpty(); int value = arr[front]; front = (front+1)%maxSize; return value; } //隊(duì)列中的有效值個(gè)數(shù) public int size(){ return (rear-front+maxSize)%maxSize; } //展示隊(duì)列的所有數(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); } //展示位于隊(duì)列頭部的元素值,不改變front的指向 public void headQueue(){ //判空 checkEmpty(); System.out.printf("頭部數(shù)據(jù)是:%d\n",arr[front]); } //檢測(cè)出隊(duì)列為空時(shí),打印當(dāng)前front,rear的值,拋出異常 public void checkEmpty(){ if (isEmpty()) { System.out.printf("當(dāng)前front=%d,rear=%d\n",front,rear); throw new RuntimeException("隊(duì)列為空,不能取數(shù)據(jù)"); } } //檢測(cè)出隊(duì)列滿時(shí),打印當(dāng)前front,rear的值,拋出異常 public void checkFull(){ if(isFull()){ System.out.printf("當(dāng)前front=%d,rear=%d\n",front,rear); throw new RuntimeException("隊(duì)列已滿,不能添加數(shù)據(jù)"); } } }
五、運(yùn)行結(jié)果
到此這篇關(guān)于Java基礎(chǔ)之?dāng)?shù)組模擬循環(huán)隊(duì)列的文章就介紹到這了,更多相關(guān)Java數(shù)組模擬循環(huán)隊(duì)列內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java多線程之循環(huán)柵欄技術(shù)CyclicBarrier使用探索
這篇文章主要介紹了Java多線程之循環(huán)柵欄技術(shù)CyclicBarrier,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪<BR>2024-01-01mybatis中如何傳遞單個(gè)String類型的參數(shù)
這篇文章主要介紹了mybatis中如何傳遞單個(gè)String類型的參數(shù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11SpringCloud容器化服務(wù)發(fā)現(xiàn)及注冊(cè)實(shí)現(xiàn)方法解析
這篇文章主要介紹了SpringCloud容器化服務(wù)發(fā)現(xiàn)及注冊(cè)實(shí)現(xiàn)方法解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08ThreadLocal?在上下文傳值場(chǎng)景實(shí)踐源碼
這篇文章主要為大家介紹了ThreadLocal在上下文傳值場(chǎng)景下的實(shí)踐源碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-03-03