數據結構:隊列
阿新 • • 發佈:2018-10-05
turn docs size ces 限制 color 操作 nbsp oid
數據結構:隊列
先入先出的數據結構
說明
在先入先出數據結構中,將首先處理隊列中的第一個元素,即front所指的位置元素。
如上圖所示,隊列是典型的 FIFO 數據結構。插入(insert)操作也稱作入隊(enqueue),新元素始終被添加在隊列的末尾
。 刪除(delete)操作也被稱為出隊(dequeue)。 你只能移除第一個元素
。
示例
入隊操作
出隊操作
隊列實現
為了實現隊列,我們可以使用動態數組和指向隊列頭部的索引。
如上所述,隊列應支持兩種操作:入隊和出隊。入隊會向隊列追加一個新元素,而出隊會刪除第一個元素。 所以我們需要一個索引來指出起點。
// "static void main" must be defined in a public class. class MyQueue { // store elements private List<Integer> data; // a pointer to indicate the start position private int p_start; public MyQueue() { data = new ArrayList<Integer>(); p_start = 0; } /** Insert an element into the queue. Return true if the operation is successful. */ public boolean enQueue(int x) { data.add(x); return true; }; /** Delete an element from the queue. Return true if the operation is successful. */ public boolean deQueue() { if (isEmpty() == true) { return false; } p_start++; return true; } /** Get the front item from the queue. */ public int Front() { return data.get(p_start); } /** Checks whether the queue is empty or not. */ public boolean isEmpty() { return p_start >= data.size(); } }; public class Main { public static void main(String[] args) { MyQueue q = new MyQueue(); q.enQueue(5); q.enQueue(3); if (q.isEmpty() == false) { System.out.println(q.Front()); } q.deQueue(); if (q.isEmpty() == false) { System.out.println(q.Front()); } q.deQueue(); if (q.isEmpty() == false) { System.out.println(q.Front()); } } }
上面的實現很簡單,但在某些情況下效率很低。 隨著起始指針的移動,浪費了越來越多的空間。 當我們有空間限制時,這將是難以接受的。
如果我們出隊了一個元素,此時第一個位置將空出來,這個空間的浪費我們可以使用循環隊列來解決。
循環隊列
說明
循環隊列是一種線性數據結構,其操作表現基於 FIFO(先進先出)原則並且隊尾被連接在隊首之後以形成一個循環。它也被稱為“環形緩沖器”。
循環隊列的一個好處是我們可以利用這個隊列之前用過的空間。在一個普通隊列裏,一旦一個隊列滿了,我們就不能插入下一個元素,即使在隊列前面仍有空間。但是使用循環隊列,我們能使用這些空間去存儲新的值。
實現
class MyCircularQueue { private int[] data; private int head; private int tail; private int size; /** Initialize your data structure here. Set the size of the queue to be k. */ public MyCircularQueue(int k) { data = new int[k]; head = -1; tail = -1; size = k; } /** Insert an element into the circular queue. Return true if the operation is successful. */ public boolean enQueue(int value) { if (isFull() == true) { return false; } if (isEmpty() == true) { head = 0; } tail = (tail + 1) % size; data[tail] = value; return true; } /** Delete an element from the circular queue. Return true if the operation is successful. */ public boolean deQueue() { if (isEmpty() == true) { return false; } if (head == tail) { head = -1; tail = -1; return true; } head = (head + 1) % size; return true; } /** Get the front item from the queue. */ public int Front() { if (isEmpty() == true) { return -1; } return data[head]; } /** Get the last item from the queue. */ public int Rear() { if (isEmpty() == true) { return -1; } return data[tail]; } /** Checks whether the circular queue is empty or not. */ public boolean isEmpty() { return head == -1; } /** Checks whether the circular queue is full or not. */ public boolean isFull() { return ((tail + 1) % size) == head; } } /** * Your MyCircularQueue object will be instantiated and called as such: * MyCircularQueue obj = new MyCircularQueue(k); * boolean param_1 = obj.enQueue(value); * boolean param_2 = obj.deQueue(); * int param_3 = obj.Front(); * int param_4 = obj.Rear(); * boolean param_5 = obj.isEmpty(); * boolean param_6 = obj.isFull(); */
隊列用法
除基本Collection
操作外,隊列還提供額外的插入,提取和檢查操作。這些方法中的每一種都以兩種形式存在:一種在操作失敗時拋出異常,另一種返回特殊值(null或false,具體取決於操作)。後一種形式的插入操作專門用於容量限制的隊列 實現; 在大多數實現中,插入操作不會失敗。
// "static void main" must be defined in a public class. public class Main { public static void main(String[] args) { // 1. Initialize a queue. Queue<Integer> q = new LinkedList(); // 2. Get the first element - return null if queue is empty. System.out.println("The first element is: " + q.peek()); // 3. Push new element. q.offer(5); q.offer(13); q.offer(8); q.offer(6); // 4. Pop an element. q.poll(); // 5. Get the first element. System.out.println("The first element is: " + q.peek()); // 7. Get the size of the queue. System.out.println("The size is: " + q.size()); } }
數據結構:隊列