一、隊列
1. 隊列的概念
- 隊列的核心理念是:先進先出;
- 隊列是一種特殊的線性表:它只允許在表的前端
(front)
進行刪除操作,而在表的後端(tail)進行插入操作
; - 隊列和棧都是一種操作受限的線性表,其中進行插入操作的端稱之爲隊尾,進行刪除操作的端稱之爲隊首;
2.隊列的屬性
getFront()
:獲取隊首的元素,但不進行出隊操作;getSize()
:獲取隊列中元素的數量;isEmpty()
:判斷隊列是否爲空;enqueue()
:在隊尾tail
插入元素;dequeue()
:在隊首front
刪除元素;
上述隊列的屬性抽象成接口,其代碼實現如下:
/**
* @Author: zjtMeng
* @Date: 2019/12/22 18:47
* @Version 1.0
*/
public interface Queue<E> {
void enqueue(E e);
E dequeue();
E getFront();
int getSize();
boolean isEmpty();
}
二、普通隊列ArrayQueue
-
普通隊列概念是:底層通過數組來實現,且通過調用
addLast()
實現入隊操作,調用removeFirst()
實現出隊操作; -
此部分會用到之前自己封裝的數組,其博客地址如下:自己封裝的數組Array
2.1基本方法的實現:
- 隊列的有參構造方法和無參構造方法初始化隊列的容積,可以直接調用
Array
的構造方法
public ArrayQueue(int capacity){
array =new Array<>(capacity);
}
public ArrayQueue(){
array = new Array<>();
}
- 入隊操作,通過調用
Array
中的addLast()
方法。由於Array
中在設計addLast()
方法時,已經考慮了擴容的操作,因此實現隊列的入隊操作時,不必考慮擴容這部分情況;
Array
中addLast()
方法和擴容操作代碼:
/**
* 調用add()方法,實現在所有元素之後添加一個新元素
*/
public void addLast(E e){
add(size,e);
}
/**
* 在index位置上插入元素e
* @param index
* @param e
*/
public void add(int index,E e){
//判斷傳入的插入位置參數是否規範以及合乎要求,
if (index <0 || index> size)
throw new IllegalArgumentException("add failed. Require index >=0 || index < size");
//判斷當前數組是否已經達到容量了
if (size == data.length)
//調用resize()方法,進行擴容
resize(2 * data.length);
//從插入位置開始,後面的所有元素全部向後挪一位
for (int i=size-1; i>=index; i--)
data[i+1] = data[i];
data[index] = e;
size++;
}
/**
* 擴容
* @param newCapacity
*/
private void resize(int newCapacity){
E[] newData = (E[]) new Object[newCapacity];
for (int i=0; i<size; i++){
newData[i] = data[i];
}
data = newData;
}
此處隊列調用Array
中的addLast()
方法,可以實現入隊操作;
- 出隊操作,通過調用
Array
中removeFirst()
方法。同樣的,由於Array
中在設計removeFirst()
方法時,已經考慮了縮容的操作,因此實現隊列的入隊操作時,不必考慮擴容這部分情況;
Array
中removeFirst()
方法和縮容操作代碼:
/**
* 刪除數組最後一個元素,返回刪除的元素
* @return
*/
public E removeLast(){
return remove(size-1);
}
/**
* 從數組中刪除指定位置的元素,並返回刪除的元素
* @param index
* @return
*/
public E remove(int index){
//判斷傳入的插入位置參數是否規範以及合乎要求,
if (index <0 || index> size)
throw new IllegalArgumentException("add failed. Require index >=0 || index < size");
E ret = data[index];
for (int i = index; i < size ; i++) {
data[i] = data[i+1];
}
size--;
//此處將移除位置置爲null,是爲了 loitering object != memory leak
data[size] = null;
//當數組元素減少到一定程度(數組的容量的1/4。而不是1/2)時,數組容量縮小一倍,從而避免數組在1/2容積節點處位置來回擴容縮容操作
if(size == data.length / 4 && data.length / 2 != 0)
resize(data.length / 2);
return ret;
}
因此此處隊列調用Array
中的removeFirst()
方法,可以實現出隊操作;
2.2普通隊列的實現
代碼如下:
package dataStructure.chapter3;
import dataStructure.chapter1.Array;
/**
* @Author: zjtMeng
* @Date: 2019/12/22 18:50
* @Version 1.0
*/
public class ArrayQueue<E> implements Queue<E> {
private Array<E> array;
//有參構造方法
public ArrayQueue(int capacity){
array =new Array<>(capacity);
}
public ArrayQueue(){
array = new Array<>();
}
@Override
public void enqueue(E e) {
array.addLast(e);
}
@Override
public E dequeue() {
return array.removeFirst();
}
@Override
public E getFront() {
return array.getFirst();
}
@Override
public int getSize() {
return array.getSize();
}
@Override
public boolean isEmpty() {
return array.isEmpty();
}
public int getCapacity(){
return array.getCapacity();
}
public String toString(){
StringBuilder res = new StringBuilder();
res.append("Queue");
res.append("front[");
for (int i = 0; i<array.getSize(); i++){
res.append(array.get(i));
if (i != array.getSize()-1)
res.append(", ");
}
res.append("] tail");
return res.toString();
}
}