在前面一篇文章中,和大家分享了一種簡單的資料結構—–列表。今天和大家分享的是另外一種類似但本質又不盡相同的一種資料結構—–佇列。
我們用這樣乙個現實生活中的例子來引出佇列,以及其和列表的區別:
現實生活中,我們以排隊買票為例,假設把買票時人們排的隊伍想象成乙個容器,那麼我們可以得到這樣的結論:先排隊的人總是先買到票。抽象出來,就可以得到佇列的基本思想:fifo即 first in first out。
定義:a restricted form of list - insert at one end, remove from the other.
有了上面的思想,就很容易可以得到對於佇列的兩種操作:
插入:我們把這個操作過程稱為入隊(enqueue);
刪除:稱之為出隊(dequeue)
我們先考慮在乙個陣列中來實現上述兩種操作。要實現從陣列一端插入,從另一端刪除,有這樣兩個關鍵的問題:第一就是如何標記第乙個元素和最後乙個元素(因為佇列總是處於動態變化中的);第二個就是標記了之後如何動態的維護第一元素位置和最後元素位置。為此,我們引入兩個變數,front標記第乙個元素,rear標記最後乙個元素。從rear端入隊,從front端出隊。
很自然的,我們可以想到用下面這種形式來表示:
但是隨著不斷的入隊和出對操作,很快又會產生另外乙個問題:如下圖示,這個時候佇列空間明明還有空位,那麼如何再插入乙個元素呢?
為了解決這個問題,我們引入如下環形佇列來表示:
這樣就可以解決上述空間有冗餘但是無法插入新元素的問題。但是很快的,乙個新的問題就產生了:
如上圖所示,對於佇列空和佇列滿,都滿足front=(rear+1)%size的關係,那麼如何區分這兩種截然不同的狀態呢?
下面我們直接給出解決方案:對於n大小的佇列,只存(n-1)個元素即可。如下圖:
雖然浪費了乙個元素儲存空間,但是相比於帶狀佇列(第
一、二副圖)已經節省了很多空間了,而且在實際應用中,佇列往往很大,相對於乙個很大的佇列來說,乙個單位的儲存空間開銷是可以忽略的。
下面給出佇列的**實現(c++):
1:基於陣列:
class aqueue
~aqueue()
int getlength() const
bool frontvalue(int& it) const
void clear()
//入隊
bool enqueue(const
int& it)
//出隊
bool dequeue(int& it)
};
2:基於鍊錶:
//linked queue
class queuenode
};class lqueue
~lqueue()
void clear()
length = 0;
}bool frontvalue(int& it)
bool enqueue(const
int& it)
length++;
return
true;
}bool dequeue(int& it)
int getlength()
};
資料結構(二) 佇列
一 佇列定義 佇列是限定在一端進行插入,另一端進行刪除特殊線性表。二 佇列基本操作 入隊出隊 三 佇列例題 1.例1 舞伴配對問題 分析 這一題是一道經典的取模運算,每一次將編號往前加一位,到達n就取模。include include include include int main return ...
資料結構 二 (佇列)
在模擬實現 佇列前應先簡單的了解先佇列的一些特點 佇列是一種特殊的線性表,特殊之處在於它只允許在表的前端 front 進行刪除操作,而在表的後端 rear 進行插入操作,和棧一樣,佇列是一種操作受限制的線性表。進行插入操作的端稱為隊尾,進行刪除操作的端稱為隊頭。佇列中沒有元素時,稱為空佇列。佇列最大...
演算法與資料結構 二 佇列
佇列也是一種線性的資料結構,它與鍊錶的區別在於鍊錶可以在任意位置進行插入刪除操作,而佇列只能在一端進行插入,另一端進行刪除。它對應於現實世界中的排隊模型。佇列有兩種常見的實現方式 基於列表的實現和基於陣列的實現 基於鍊錶的佇列,我們需要儲存兩個指標,乙個指向頭節點,乙個指向尾節點。這種佇列不存在佇列...