資料結構與算法系列(2)資料結構之佇列詳解
阿新 • • 發佈:2020-12-11
資料結構之佇列詳解
1、概述
佇列(Queue)是一種常用的資料結構,佇列(Queue)是一個有序列表,可以用陣列
或是連結串列
來實現。佇列(Queue)遵循先入先出的原則。即:先存入佇列的資料,要先取出,後存入的要後取出。佇列只允許在後端(tail
)進行插入操作,在前端(head
)進行出佇列(刪除)操作。
2、使用陣列實現佇列思路
佇列是有序列表,若使用陣列的結構來儲存佇列的資料,則佇列陣列的宣告,如下圖:
head
和tail
分別記錄佇列前後端的下標,head
rear
則是隨著資料輸入而改變。
藉助以下動態圖,能更好的理解,佇列的新增和刪除。
3、簡單佇列程式碼實現
基於java實現簡單佇列。
public class ArrayQueue {
/**
* 佇列頭部
*/
private int head;
/**
*佇列尾部
*/
private int tail;
/**
* 存放資料
*/
private int[] array;
/**
*
*/
private int capacity;
/**
* 初始化陣列
* @param capacity
*/
public ArrayQueue(int capacity) {
this.capacity = capacity;
//初始化陣列
this.array=new int[capacity];
}
/**
* 入隊
*/
public void add(int n){
if (isFull()){
throw new RuntimeException("佇列已經滿了" );
}
array[tail]=n;
//隊尾後移
tail++;
}
/**
* 出佇列
* @return
*/
public int pop(){
if (isEmpty()){
throw new RuntimeException("佇列為空");
}
int value=array[head];
//頭部指標後移
head++;
return value;
}
/**
* 獲取佇列頭資料
* @return
*/
public int getFirst(){
if (isEmpty()){
throw new RuntimeException("佇列為空");
}
return array[head];
}
/**
* 獲取佇列頭資料
* @return
*/
public int getLast(){
if (isEmpty()){
throw new RuntimeException("佇列為空");
}
return array[tail];
}
/**
* 佇列是否為空
* @return
*/
public boolean isEmpty(){
return head==tail;
}
/**
* 佇列是否滿了
* @return
*/
public boolean isFull(){
return tail==capacity;
}
}
測試程式碼
public static void main(String[] args) {
ArrayQueue arrayQueue=new ArrayQueue(5);
arrayQueue.add(1);
arrayQueue.add(2);
arrayQueue.add(3);
arrayQueue.add(4);
arrayQueue.add(5);
System.out.println(arrayQueue.pop());
System.out.println(arrayQueue.getFirst());
arrayQueue.add(6);
}
上面實現的簡單佇列,有如下問題:佇列只能使用一次就不能用,即:當佇列新增資料加滿後,即使有資料出隊列了,也不能再新增新的資料。下面介紹的環形佇列,可以解決此問題。
4、環形佇列
public class CirleArrayQueue {
/**
* 測試
* @param args
*/
public static void main(String[] args) {
CirleArrayQueue cirleArrayQueue=new CirleArrayQueue(6);
cirleArrayQueue.add(1);
cirleArrayQueue.add(2);
cirleArrayQueue.add(3);
cirleArrayQueue.add(4);
cirleArrayQueue.add(5);
System.out.println("原始佇列中的資料~~~~");
cirleArrayQueue.list();
System.out.println("出佇列的資料:"+ cirleArrayQueue.pop());
cirleArrayQueue.list();
System.out.println("新增資料後,佇列中的資料~~~~~");
cirleArrayQueue.add(6);
cirleArrayQueue.list();
}
/**
* 佇列頭部
*/
private int head;
/**
*佇列尾部
*/
private int tail;
/**
* 存放資料
*/
private int[] array;
/**
*
*/
private int capacity;
/**
* 初始化陣列
* @param capacity
*/
public CirleArrayQueue(int capacity) {
this.capacity = capacity;
//初始化陣列
this.array=new int[capacity];
}
/**
* 入隊
*/
public void add(int n){
if (isFull()){
throw new RuntimeException("佇列已經滿了");
}
array[tail]=n;
//因為是環形佇列,使用取模
tail=(tail+1)%capacity;
}
/**
* 出佇列
* @return
*/
public int pop(){
if (isEmpty()){
throw new RuntimeException("佇列為空");
}
int value=array[head];
//頭部指標後移
head=(head+1)%capacity;
return value;
}
/**
* 獲取佇列頭資料
* @return
*/
public int getFirst(){
if (isEmpty()){
throw new RuntimeException("佇列為空");
}
return array[head];
}
/**
* 獲取佇列頭資料
* @return
*/
public int getLast(){
if (isEmpty()){
throw new RuntimeException("佇列為空");
}
return array[tail];
}
/**
* 佇列是否為空
* @return
*/
public boolean isEmpty(){
return head==tail;
}
/**
* 佇列是否滿了
* @return
*/
public boolean isFull(){
return (tail+1)%capacity==head;
}
public int size(){
return (tail+capacity-head)%capacity;
}
public void list(){
for (int i = head; i <head+size() ; i++) {
if (array[i]!=0)
System.out.println(array[i]);
}
}
}