单片机实现环形队列_稀疏数组和队列(二)
隊列的介紹
隊列以一種先入先出(FIFO)的線性表,還有一種先入后出的線性表(FILO)叫做棧。
教科書上有明確的定義與描述。類似于現實中排隊時的隊列(隊尾進,隊頭出),隊列只在線性表兩端進行操作,插入元素的一端稱為表尾,刪除(取出)元素的一端稱為表頭。分別對應于 入隊和出隊操作。
存儲結構:
· 線性存儲結構,稱為順序隊列,使用數組實現
· 鏈式存儲結構,稱為鏈隊,使用鏈表實現。
圖解入隊操作
圖解出隊操作
隊列的使用場景
數組模擬順序隊列
代碼實現:
/** * All rights Reserved, Designed By https://www.tulingxueyuan.com/ * @Title: ArrayQueue.java * @Package com.tuling.queue2 * @Description: * @author: 小白 * @Date 2019年11月11日 下午5:54:51 * @version V1.0 * @Copyright: */ package com.tuling.queue2;/** * @ClassName ArrayQueue * @Description * @Author 北京圖靈學院 * @Date 2019年11月11日 下午5:54:51 */public class ArrayQueue {//定義一個數組,用來模擬隊列,存儲數據private Integer[] arr;//定義一個變量,用來指向隊列頭private int front;//定義一個變量,用來指向隊列尾private int rear;/** * * @Title: ArrayQueue * @Description: 構造方法 * @param queueSize:隊列初始化容量。 * @throws */public ArrayQueue(int queueSize) {if(queueSize < 0) {throw new IllegalArgumentException("初始化容量不能小于0");}arr = new Integer[queueSize];front = 0;rear = 0;}/** * * @Title: addQueue * @Description: 入隊操作: * 1、首先判斷隊列容量情況 * 2、如果隊列未滿,隊列頭不變,向隊列尾下標位置插入數據,同時,隊列尾+1 * @param: @param num * @return: void * @throws */public void addQueue(int num) {if(isFull()) {throw new IllegalArgumentException("隊列已滿!");}arr[rear] = num;rear++;}/** * * @Title: isFull * @Description: 判斷隊列是否已滿 * @return: boolean * @throws */public boolean isFull() {return rear == arr.length;}/** * * @Title: getQueue * @Description: 出隊操作 * 1、先判讀當前隊列是否為空 * 2、每次從隊列頭開始出隊,出隊一個元素,隊列頭+1 * @param: * @return: int * @throws */public int getQueue() {if(isEmpty()) {throw new IllegalArgumentException("隊列為空!");}return arr[front++];}/** * * @Title: isEmpty * @Description: 判斷當前隊列是否為空 * @return: boolean * @throws */public boolean isEmpty() {return front == rear;}/** * * @Title: showQueue * @Description:顯示隊列的所有數據 * @param: * @return: void * @throws */public void showQueue() {if(isEmpty()) {throw new IllegalArgumentException("隊列為空!");}for (int i = front; i < rear; i++) {System.out.println(i + " --> " + arr[i]);}}}/** * All rights Reserved, Designed By https://www.tulingxueyuan.com/ * @Title: ArrayQueueDemo.java * @Package com.tuling.queue2 * @Description: * @author: 小白 * @Date 2019年11月11日 下午6:22:00 * @version V1.0 * @Copyright: */ package com.tuling.queue2;/** * @ClassName ArrayQueueDemo * @Description * @Author 北京圖靈學院 * @Date 2019年11月11日 下午6:22:00 */public class ArrayQueueDemo {/** * @Title: main * @Description: * @param: @param args * @return: void * @throws */public static void main(String[] args) {ArrayQueue aq = new ArrayQueue(5);aq.addQueue(5);aq.addQueue(8);aq.addQueue(7);aq.showQueue();System.out.println("------------------------------------");aq.addQueue(2);aq.addQueue(9);//aq.addQueue(9);aq.showQueue();System.out.println("------------------------------------");System.out.println("出隊");aq.getQueue();aq.showQueue();System.out.println("------------------------------------");System.out.println("出隊");aq.getQueue();aq.showQueue();System.out.println("------------------------------------");System.out.println("出隊");aq.getQueue();aq.showQueue();System.out.println("------------------------------------");System.out.println("出隊");aq.getQueue();aq.showQueue();System.out.println("------------------------------------");System.out.println("出隊");aq.getQueue();aq.showQueue();}}順序隊列的溢出現象
· "下溢"現象:當隊列為空時,做出隊運算產生的溢出現象。"下溢"是正常現象,常用作程序控制轉移的條件。
· "真上溢"現象:當隊列滿時,做進棧運算產生空間溢出的現象。"真上溢"是一種出錯狀態,應設法避免。
· "假上溢"現象:由于入隊和出隊操作中,頭尾指針只增加不減小,致使被刪元素的空間永遠無法重新利用。當隊列中實際的元素個數遠 遠小于向量空間的規模時,也可能由于尾指針已超越向量空間的上界而不能做入隊操作。該現象稱為"假上溢"現象。
數組模擬環形隊列
為了解決順序隊列中"假上溢"的現象,同時更好的利用內存空間,我們將其實現為環形隊列。
理解環形隊列
首先我們要說明的是循環隊列仍然是基于數組實現的。但是為了形象化的說明問題,我們如下圖所示
1. 圖中有兩個指針(其實就是兩個整數型變量,因為在這里有指示作用,所以這里理解為指針)front、rear,一個指示隊頭,一個指示隊尾。
2. rear和front互相追趕著,這個追趕過程就是隊列添加和刪除的過程,如果rear追到head說明隊列滿了,如果front追到rear說明隊列為空。
3. 我們把它掰彎,用的是求余,這樣兩個值就不會跑出最大范圍,并且可以實現彎曲的效果,所以說對于循環隊列我們必須給定最大值。這其實是我們臆想的,我們要做的就是利用循環來解決空間浪費的問題。
環形隊列的實現過程
· 當添加一個元素時,(rear+1)%MAXQSIZE; //理解為什么求余?
· 當刪除一個元素時,(front+1)%MAXQSIZE;//理解為什么求余?
· 當rear=front的時候,隊列可能是滿,也可能是空。
· 因為存在滿和空兩種情況,我們需要分別判斷:
· 滿:當隊列添加元素到rear的下一個元素是head的時候,也就是轉圈子要碰頭了,我們就認為隊列滿了。(rear+1)%MAXSIZE=Q.front
· 空:當隊列刪除元素到head=rear的時候,我們認為隊列空了。rear==front,不一定為0
環形隊列代碼實現
CircularQueue.java 類代碼如下:
/** * All rights Reserved, Designed By https://www.tulingxueyuan.com/ * @Title: CircularQueue.java * @Package com.tuling.circular * @Description: * @author: 北京圖靈學院 * @date: 2019年11月13日 下午5:13:16 * @version V1.0 * @Copyright: */package com.tuling.circular;/** * @ClassName CircularQueue * @Description * @Author 北京圖靈學院 */public class CircularQueue {//該數組模擬環形隊列,存儲數據private Integer[] arr;//該變量指向隊頭private int front;//該變量指向隊尾private int rear;//該變量表示當前隊列的最大容量private int maxSize;//該變量表示當前隊列有效數據的個數private int elementCount;/** * * @param queueSize:隊列的初始容量 */public CircularQueue(int queueSize) {if(queueSize < 0) {throw new IllegalArgumentException("初始化容量不能小于0!");}arr = new Integer[queueSize];maxSize = queueSize;front = 0;rear = 0;elementCount=0;}/** * * @Title: addQueue * @Description:入隊操作 * 思路: * 1、判斷隊列是否已滿 * 2、向隊尾插入數據 * 3、將有效數據的個數 + 1 * @param: num * @return: void * @throws */public void addQueue(int num) {if(isFull()) {throw new IllegalArgumentException("隊列已滿!");}//隊列未滿,可以繼續入隊操作//想隊尾插入數據arr[rear] = num;//移動尾指針rear = (rear + 1) % maxSize;elementCount+=1;}/** * * @Title: isFull * @Description:判斷當前隊列是否已滿 * 判滿條件: * 1、空出一個元素位置,區別隊列判空的條件 * 2、保證隊尾指針的范圍在數組下標范圍內,解決方案:對Maxsize取余 * (rear + 1) % maxSize == front * @param: * @return: boolean * @throws */public boolean isFull() {return (rear + 1) % maxSize == front;}/** * * @Title: showQueue * @Description:顯示隊列當中的所有數據 * @param: * @return: void * @throws */public void showQueue() {if(isEmpty()) {throw new IllegalArgumentException("隊列為空!");}for(int i = front; i < (front+elementCount);i++) {System.out.println((i%maxSize) + " --> " + arr[i%maxSize]);}}/** * * @Title: isEmpty * @Description:判斷當前隊列是否為空 * @param: * @return: boolean * @throws */public boolean isEmpty() {return front == rear;}/** * * @Title: getQueue * @Description: 出隊操作 * 思路:出隊需要操作隊頭后移,還需要注意隊頭的值范圍。 * 1、先用一個臨時變量存儲當前隊頭 * 2、將隊頭后移 * front = (front + 1) % maxSize * 3、將有效數據個數 -1 * 4、return * @param: * @return: int * @throws */public int getQueue() {if(isEmpty()) {throw new IllegalArgumentException("隊列為空!");}int tempHead = arr[front];front = (front + 1) % maxSize;elementCount-=1;return tempHead;}/** * * @Title: showHead * @Description:顯示當前隊列頭,不進行出隊操作 * @param: * @return: void * @throws */public void showHead() {if(isEmpty()) {throw new IllegalArgumentException("隊列為空!");}System.out.println("當前隊列的隊列頭為:" + front + " --> " + arr[front]);}}測試代碼:
/** * All rights Reserved, Designed By https://www.tulingxueyuan.com/ * @Title: CircularQueueDemo.java * @Package com.tuling.circular * @Description: * @author: 北京圖靈學院 * @date: 2019年11月13日 下午5:30:43 * @version V1.0 * @Copyright: */package com.tuling.circular;/** * @ClassName CircularQueueDemo * @Description * @Author 北京圖靈學院 */public class CircularQueueDemo {/** * @Title: main * @Description: * @param: @param args * @return: void * @throws */public static void main(String[] args) {CircularQueue cq = new CircularQueue(5);System.out.println("--------------------------1.入隊操作-----------------------------");cq.addQueue(5);cq.addQueue(8);cq.addQueue(7);cq.addQueue(2);//cq.addQueue(9);cq.showQueue();System.out.println("--------------------------2.入隊操作-----------------------------");System.out.println("出隊:" + cq.getQueue());cq.showHead();System.out.println("出隊:" + cq.getQueue());cq.showHead();System.out.println("出隊:" + cq.getQueue());cq.showHead();System.out.println("出隊:" + cq.getQueue());System.out.println("--------------------------3.入隊操作-----------------------------");cq.addQueue(5);cq.addQueue(8);cq.addQueue(7);cq.addQueue(2);cq.showQueue();}}總結
以上是生活随笔為你收集整理的单片机实现环形队列_稀疏数组和队列(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ibatis mysql 同时删多个表报
- 下一篇: 循环链表、双链表