資料結構(3):佇列的原理和實現
阿新 • • 發佈:2019-10-03
完整程式碼拉到最底下
一、介紹
佇列顧名思義就像我們生活中排隊一樣,先進先出。
如上圖所示,25、16、5、9依次在佇列中,按照順序拿出的資料也分別是25、26、5、9。
二、實現過程及思路
底層使用陣列來實現,實現的功能有插入資料到隊尾、移除隊首資料、檢視隊首資料、判斷佇列是否為空、判斷佇列是否存滿。
將佇列的元素儲存在陣列的某個區間內,佇列在陣列中是連續的,所以使用變數標記佇列在陣列中的位置。
1、編寫類及屬性
我們可以使用elements變數標記佇列中元素的數量,使用front變數標記隊首元素在陣列的索引,end變數標記隊尾元素在陣列中的索引。
public class MyQueue { private Object[] arr;//存放佇列元素的陣列 private int elements;//佇列元素數量 private int front;//隊頭元素在陣列中的索引 private int end;//隊尾元素在陣列中的索引 public MyQueue() { arr = new Object[10]; elements = 0; front = 0; end = -1; } public MyQueue(int maxSize) { arr = new Object[maxSize]; elements = 0; front = 0; end = -1; } }
2、佇列是否為空
標記佇列元數量的變數 elements 為 0 即為空
public boolean isEmpty() {
return elements == 0;
}
3、佇列是否已經滿了
佇列元素個數與陣列的長度相等即為滿
public boolean isFull() {
return elements == arr.length;
}
4、獲取隊頭元素
獲取陣列中索引為 front
的元素
public Object peek() {
return arr[front];
}
5、移除隊首元素
每次都是移除陣列中索引為 front
的元素,下一個元素就變成了隊首,即front+1
elements-1
。共有三種情況要考慮,如果佇列已經空了就無須做任何操作,如果已經是最後一個元素,直接將標記位置的變數重置即可,其他情況正常操作。
public Object remove() { if (isEmpty()) { throw new RuntimeException("佇列已經是空的,放心使用吧"); } Object value = arr[front++]; //如果已經是最後一個元素了,將指標重置即可 if (elements == 1) { end = -1; front = 0; elements = 0; } else { elements--; } return value; }
6、插入
我們編寫一個持續可用的佇列,所以要考慮到以下情況。
(1)儲存佇列的陣列滿了(佇列滿了),這個好理解,滿了就無法向隊尾加入元素了。
(2)因為佇列在陣列中是連續的,如果佇列的元素在陣列中最後,需要將元素從隊首到隊尾移到陣列中第一位,也就是將後面的位置空出來(參考下圖)。
public void insert(Object value) {
//檢測佇列是否已經滿了
if (isFull()) {
throw new RuntimeException("佇列內元素已達到設定長度");
}
//如果後面沒有空位置,將餘下元素放到陣列的頭
if (elements > 1 && end == arr.length - 1) {
int i = 0;
for (; i < elements; i++, front++) {
arr[i] = arr[front];
}
front = 0;
end = i-1;
}
//其他情況正常向後新增元素
arr[++end] = value;
elements++;
}
7、測試
public static void main(String[] args) {
MyQueue queue = new MyQueue(4);
queue.insert(11);
queue.insert(12);
queue.insert(13);
queue.insert(14);
queue.remove();
queue.remove();
queue.insert(16);
//queue.remove();
//queue.remove();
//queue.insert(19);
//queue.insert(20);
queue.remove();
queue.remove();
queue.insert(21);
queue.insert(22);
while (!queue.isEmpty()) {
System.out.println(queue.remove());
}
}
三、完整程式碼
package com.jikedaquan.datastruct;
public class MyQueue {
private Object[] arr;
private int elements;//佇列元素數量
private int front;//隊頭元素在陣列中的索引
private int end;//隊尾元素在陣列中的索引
public MyQueue() {
arr = new Object[10];
elements = 0;
front = 0;
end = -1;
}
public MyQueue(int maxSize) {
arr = new Object[maxSize];
elements = 0;
front = 0;
end = -1;
}
//從隊尾插入
public void insert(Object value) {
//檢測佇列是否已經滿了
if (isFull()) {
throw new RuntimeException("佇列內元素已達到設定長度");
}
//如果後面沒有空位置,將餘下元素放到陣列的頭
if (elements > 1 && end == arr.length - 1) {
int i = 0;
for (; i < elements; i++, front++) {
arr[i] = arr[front];
}
front = 0;
end = i-1;
}
arr[++end] = value;
elements++;
}
//刪除資料,從隊頭刪除
public Object remove() {
if (isEmpty()) {
throw new RuntimeException("佇列已經是空的,放心使用吧");
}
Object value = arr[front++];
//如果已經是最後一個元素了,將指標重置即可
if (elements == 1) {
end = -1;
front = 0;
elements = 0;
} else {
elements--;
}
return value;
}
//檢視資料,從隊頭檢視
public Object peek() {
return arr[front];
}
//判斷是否為空
public boolean isEmpty() {
return elements == 0;
}
public boolean isFull() {
return elements == arr.length;
}
public static void main(String[] args) {
MyQueue queue = new MyQueue(4);
queue.insert(11);
queue.insert(12);
queue.insert(13);
queue.insert(14);
queue.remove();
queue.remove();
queue.insert(16);
// queue.remove();
// queue.remove();
// queue.insert(19);
// queue.insert(20);
queue.remove();
queue.remove();
queue.insert(21);
queue.insert(22);
while (!queue.isEmpty()) {
System.out.println(queue.remove());
}
}
}