銀行叫號排隊的案例佇列是乙個有序列表,可以用陣列或鍊錶來實現。
遵循先入先出的原則。例如:銀行先叫號的人先於後叫號的人辦理業務。誰先叫號誰先辦理,誰後叫號誰後辦理。即:先進入佇列的資料先取出,後進入佇列的資料後取出。
示意圖(使用陣列模擬佇列示意圖)
佇列本身是有序列表,若使用陣列的結構來儲存佇列的資料,則佇列陣列的宣告如上圖,其中, maxsize 為佇列最大容量。
佇列的輸出、輸入分別是從佇列的頭部和尾部來處理,因此需要兩個變數 front 和 rear 來記錄佇列前後端的位置。front 隨著資料的取出而改變,rear 隨著資料的輸入而改變。
front:指向佇列的頭部資料的前乙個位置當我們將資料存入佇列時稱為"addqueue",addqueue 有兩個步驟rear:指向佇列的尾部資料
① 將佇列的尾部指標往後移一位:rear + 1;
② 當rear == maxsize - 1;則佇列已滿,無法新增資料到佇列中。反之,arr[++rear] = value。注意,新增乙個資料只需要隊尾後移一位即可。
當我們將資料從佇列中取出時稱為"getqueue",getqueue 有兩個步驟
① 將佇列的頭部指標後移一位:front + 1;
② 當front == rear;則隊列為空,沒有資料可取,否則,返回arr[++front]。
public class arrayqueuetest catch (exception e)
break;
case 'p':
try catch (exception e)
break;
case 'q':
scanner.close();
loop = false;
break;
default:
break;
}} } }
class arrayqueue
public boolean isfull()
public boolean isempty()
public void addqueue(int value)
arr[++rear] = value;
system.out.println("新增成功"); }
public int getqueue()
return arr[++front]; }
public void showqueue()
for(int i = 0; i < arr.length; i++)
system.out.println(); }
public void peek()
system.out.println(arr[front + 1]);
}}
針對上述陣列模擬佇列,在測試的時候發現,當佇列資料已滿時,無法新增資料,但是當取出乙個資料時,還是提示佇列已滿。目前陣列模擬的佇列的只能使用一次,沒有達到復用的效果。
將這個陣列使用乙個演算法,改進成 "環形佇列":取模 %
> 注意
front:在陣列模擬環形佇列中指向陣列頭部的資料,初始值為0
rear:在陣列模擬環形佇列中執行尾部資料的後一位(跟資料模擬佇列有區別),因為希望空出乙個空間作為約定,初始值為0
陣列模擬佇列之所以不能復用的原因是因為,一旦 rear == maxsize - 1; 就判斷為佇列已滿,但是在資料新增滿之後,這個 rear 在陣列模擬佇列中就不會再發生改變,沒有形成乙個環形結構。
思路就是如何讓這個 rear 在滿了之後還能再回到起點重新來過(操場跑圈),就需要在rear == maxsize - 1之後,手動將 rear 的值值為 0;front 隨著佇列中資料的取出也會逐漸趨向於 maxsize - 1,所以也需要手動將 front 的值置為0,判斷佇列已滿的條件就是 rear 所處的位置的下乙個位置就是 front 所處的位置:即 rear + 1 = front;
手動將達到最大值置為0的思路理解起來較容易,實現起來較繁瑣。
首先判斷已滿的條件為(rear + 1) % maxsize == front;maxsize 為陣列的長度,而實際佇列儲存資料的個數為 maxsize - 1 個
這樣取模的原因,如果向後面這樣取,rear % maxsize == front;在還沒向佇列新增資料時,則等式成立,無法新增資料判斷為空的條件:rear == front;
當我們如上述分析時,這時佇列中的有效資料個數為(rear + maxsize - front) % maxsize;
+maxsize 的原因,是因為,如果出現 rear 比 front 快一圈的情況(跑圈),rear - front 就會出現負數,與需求相悖。
public class circlearrayqueuetest catch (exception e)
break;
case 'p':
try catch (exception e)
break;
case 'q':
scanner.close();
loop = false;
break;
default:
break;
}} }
}class circlearrayqueue
public boolean isfull()
public boolean isempty()
public void addqueue(int value)
arr[rear] = value;
rear = (rear + 1) % maxsize; // 防止索引越界
} public int getqueue()
int value = arr[front];
front = (front + 1) % maxsize; // 防止索引越界
return value;
} public void showqueue()
for (int i = front; i < front + size(); i++)
} public int size()
public void peek()
system.out.println(arr[front]);
} public int getfront()
public int getrear()
}
資料結構(二) 佇列
一 佇列定義 佇列是限定在一端進行插入,另一端進行刪除特殊線性表。二 佇列基本操作 入隊出隊 三 佇列例題 1.例1 舞伴配對問題 分析 這一題是一道經典的取模運算,每一次將編號往前加一位,到達n就取模。include include include include int main return ...
資料結構 二 (佇列)
在模擬實現 佇列前應先簡單的了解先佇列的一些特點 佇列是一種特殊的線性表,特殊之處在於它只允許在表的前端 front 進行刪除操作,而在表的後端 rear 進行插入操作,和棧一樣,佇列是一種操作受限制的線性表。進行插入操作的端稱為隊尾,進行刪除操作的端稱為隊頭。佇列中沒有元素時,稱為空佇列。佇列最大...
演算法與資料結構 二 佇列
佇列也是一種線性的資料結構,它與鍊錶的區別在於鍊錶可以在任意位置進行插入刪除操作,而佇列只能在一端進行插入,另一端進行刪除。它對應於現實世界中的排隊模型。佇列有兩種常見的實現方式 基於列表的實現和基於陣列的實現 基於鍊錶的佇列,我們需要儲存兩個指標,乙個指向頭節點,乙個指向尾節點。這種佇列不存在佇列...