RxSwift Queue 佇列的實現

2021-09-24 06:33:27 字數 2738 閱讀 8645

在 rxswift 的框架中,在 queue.swift 檔案中使用陣列實現了乙個佇列(先進先出fifo)。在操作次數達到 n 時,入棧和出棧的複雜度為 o(1),獲取第乙個出棧元素的複雜度也為 o(1)。

下面是根據原始碼,梳理的實現原理:

queue的內部使用陣列_storage來儲存佇列中的元素,_storage 的初始容量在 queue 的初始化方法中傳入。

init(capacity: int) 

複製**

隨著元素進佇列和出佇列,陣列_storage的容量可能會改變,所以用_initialcapacity來記錄陣列的初始化容量。

當有元素進入佇列時,就從陣列 _storage 的索引為 0 處向後儲存。入佇列的元素儲存在陣列 _storage 中的索引,使用屬性_pushnextindex來表示。當有元素出佇列時,就從陣列 _storage 的索引為 0 處向後獲取,使用dequeueindex屬性來表示首先要出棧的元素在陣列 _storage 中的索引。在元素入佇列和出佇列的過程中,使用屬性_count來記錄當前棧中元素的數量。

當有元素入佇列時,如果佇列中的元素數量 _count 小於陣列 _storage 的容量_storage.count,也就是說陣列中還有空間可以繼續儲存新的佇列元素。這時如果 _pushnextindex 小於 _storage.count,則將 _pushnextindex 不斷增加,如果 _pushnextindex 大於等於 _storage.count,則說明佇列中有的元素已經出棧,在陣列的開頭處空出了位置,則將進入佇列的索引 _pushnextindex 指向陣列的索引為 0 處,繼續向後新增元素。 所以陣列中的元素排布可能為以下兩種情況:

所以 dequeueindex 可以通過 _pushnextindex 和 _count 推導出,**如下:

private var dequeueindex: int 

複製**

當有元素進入佇列時,如果佇列中的元素數量 _count 等於陣列 _storage 的容量(_storage.count)時,也就是說陣列中已經存滿了佇列的元素,這時就需要乙個更大的陣列來存放佇列元素。新的陣列的容量通過原來陣列的容量(陣列的容量大於0時)乘以係數_resizefactor計算獲得。

// 元素進入佇列的方法

mutating func enqueue(_ element: t)

_storage[_pushnextindex] = element

_pushnextindex += 1

_count += 1

// _pushnextindex 大於 _storage.count,將 _pushnextindex 指向陣列的開頭

if _pushnextindex >= _storage.count

}複製**

怎樣對儲存佇列元素的陣列進行擴容呢?分成兩步:

建立乙個容量合適的新陣列

將原來陣列中的元素複製到新的陣列中。

建立新的陣列簡單,我們應該怎樣將原來陣列中的元素拷貝到新的陣列中。我們再次看佇列元素在陣列中的可能出現的分布情況:

可以將陣列中的元素分成兩塊,第一塊是出棧位置dequeueindex到陣列末尾的元素,第二塊是陣列開頭到佇列的結尾的元素。

這種情況的第二塊的元素個數為0。

接下來計算兩塊的元素的數量。計算陣列容量和出棧的位置 dequeueindex 之間的間隔 spacetoendofqueue,則第一塊的元素個數為 spacetoendofqueue 和 _count 中較小的乙個,用 countelementsinfirstbatch 表示。第二塊的元素個數為元素的個數 _count 減去 countelementsinfirstbatch 的數量,用 numberofelementsinsecondbatch 表示。 接下來,只需要將第一段內的元素拷貝至新元素的開頭,將第二段拷貝至新陣列中第一段元素的末尾。

// 1.

mutating private func resizeto(_ size: int)

複製**

在元素出佇列的過程中,可能會出現陣列中的容量遠遠大於佇列中元素的數量,這時為了減少占用的記憶體空間,則需要縮小陣列的大小。所以在有元素出佇列時,需要根據條件判斷是否需要縮小陣列的大小。如果需要調整陣列容量,則申請乙個新的小容量陣列,再將元素拷貝至新的陣列中。將陣列容量調小的方法和將陣列調大的方法相同(都是通過呼叫resizeto(_)方法)。

// 出棧

private mutating func dequeueelementonly() -> t

return _storage[index]!

}/// dequeues element or throws an exception in

case queue is empty.

////// - returns: dequeued element.

mutating func dequeue() -> t?

defer

}return dequeueelementonly()

}複製**

佇列 優先佇列的學習

佇列定義 佇列是限定只能在表尾進行 插入,在表頭進行刪除的線性表 隊尾 允許插入的一端 隊頭 允許刪除的一端 佇列的定義 include queue 標頭檔案 using namespace std 需要加上使用名稱 空間,和sort 排序函式是一樣的。queue int q 格式 queue 型別...

佇列 迴圈佇列的實現

為了可以重新利用佇列底層陣列中已刪除元素所佔的空間,消除可能出現的 假滿 現象,將順序佇列改進為迴圈佇列。迴圈佇列是首尾相連的佇列 當front rear變數達到底層陣列的capacity 1之後,再向前以為就變成0.入隊 1 判斷佇列是否已滿,已滿丟擲越界異常 2 不滿的話把元素查到隊尾,並且re...

棧的佇列(佇列)

二.關於佇列的簡單實現。順序佇列的基本實現和順序棧的實現基本相似。順序佇列在出列和入列的時候會使佇列整體向上移動,會浪費一定的空間。因此出現了一種佇列叫做迴圈佇列。迴圈佇列可以實現空間的重複利用,大大節省了空間。關於迴圈佇列的實現 建立乙個空佇列 struct node struct node in...