佇列(Queue)與環形佇列
使用場景: 排隊買票
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
特徵
- 先進先出(FIFO)
- 有序列表,可以用陣列或連結串列來實現。
- Queue兩個指針:rear 佇列的尾部(含)、front 佇列的頭部(不含)。
- 新增數據時,front不動rear動;刪除數據時,rear不動front動 => 由尾端加入數據,由頭部取出。
我們可以以排隊買票為例,將排隊的隊列視作Queue,先排隊的人先買票,後到的人排在後面等待買票,並且先買票的人買完票之後就離開隊伍;我們將第一個買票的人稱之為front,隊伍最後一個等待買票的人為rear。
當1號買完票離開換2號買票時,此時的front變為2號。
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
當又有下一個人(5號)要買票,此時rear從4號變到5號身上。
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
因此我們可以得出,當新增數據時,front不動rear動;刪除數據時,rear不動front動。
陣列模擬佇列
當我們將數據存入佇列時稱為addQueue,addQueue的處理須要有兩個步驟:
- 將尾指針往後移:rear+1,當
front == rear
為空。
- 若尾指針 rear < maxSize-1 則將數據存入rear所指的陣列元素中;若
rear == maxSize-1
為佇列已滿。
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →
代碼實現
目前使用會遇到的困難為:佇列使用一次就不能再用,當我將數據取出,前端明明還有空位但想新增數據卻被告知佇列已滿。
因此需要優化,將之改為環形佇列。
陣列模擬環形佇列
思路分析
- front的涵義做一個調整: front就指向佇列的第一個元素,也就是說
arr[front]
就是佇列的第一個元素,front 的初始值 = 0
- rear的涵義做一個調整: rear就指向佇列的最後一個元素的後一個位置,因為希望空出一個空間用於判斷環形佇列是否為空或滿,rear 的初始值 = 0
- 當佇列滿時,條件是
(rear+1) % maxSize = front
- 當佇列為空時,條件是
rear == front
- 佇列中有效的數據個數為
(rear + maxSize - front) % maxSize
使用環形佇列後,數據可以一直刪減、新增直到沒有空餘的位置,形成一個環狀的結構,因此不會浪費多餘的空間。
舉個簡單的例子來加深印象好了:
當我今天宣告一個環形佇列 MaxSize 為4,那就代表我這個佇列有效數據最大是3,因為有一個儲存單元要預留下來判斷是否為空還是滿。
添加數據 10,20,30
arr[0] = 10 , arr[1] = 20 , arr[2] = 30
取出數據,則只剩下
arr[1] = 20 , arr[2] = 30
新增數據 40
arr[1] = 20 , arr[2] = 30 , arr[3] = 40
繼續取出 20 和 30
arr[3]=40
再去新增數據 50,60
arr[3] = 40 , arr[0] = 50 , arr[1] = 60
再把 40 取出,加入70 會變為
arr[0] = 50 , arr[1] = 60 , arr[2] = 70
小整理
佇列
- front的初始值 = -1 , rear的初始值 = -1
- 判斷佇列為空
rear == front
- 判斷佇列為滿
rear = maxSize -1
環形佇列
- front的初始值 = 0 , rear的初始值 = 0
- 需預留一個儲存單元來判斷佇列是否為空還是滿
- 判斷佇列為空
rear == front
- 判斷佇列為滿
(rear+1) % maxSize == front
- 判斷佇列的有效數據個數
(rear + maxSzie - front) % maxSize
front = 0
rear = 5
maxSize = 7
(5+7-0) % 7 = 5 ,共有五個有效數據。
為什麼不是6?
因為rear會指向最後一個元素的後一個位置。