簡體   English   中英

找到B +樹的中位數

[英]Finding the median in B+ tree

我需要實現一個B +樹。

我需要創建以下方法:

  1. 插入(x) - 0(log_t(x))。
  2. 搜索 - 成功搜索 - O(log_t(x))。 不成功的搜索 - O(1){有很高的可能性}

所以我開始實現Insert(x) - 每次我有一個完整的葉子,我想把它分成兩個分開的葉子。 一個鍵的鍵等於或低於中值鍵,第二個鍵將包含值高於中值的鍵。

如何在不損害運行時間的情況下找到此中位數?

我想過:

  1. 將每個內部節點和葉子表示為較小的B +樹,但只有當樹完全平衡時,中位數才是根(或根中的一個元素)。
  2. 將每個內部節點和葉子表示為雙向鏈表。 並且在插入輸入時嘗試獲取中值鍵,但是輸入不適用於它。
  3. 表示為數組可能會給我中間,但是當我將其拆分時,我需要至少O(n / 2)將鍵插入到新數組中。

我能做什么?

關於搜索,想法明智:成功和不成功搜索之間的區別在於在葉子中搜索,但我仍然需要通過樹的不同鍵“運行”以確定密鑰是否在樹中。 那怎么可能是O(1)?

在B +樹中,所有值都存儲在葉子中。

請注意,您可以將每個葉子的指針添加到下一個葉子,除了標准B +樹之外,您還可以獲得包含所有元素有序鏈接列表

現在,請注意,假設您知道此鏈接列表中的當前中位數是什么 - 在插入/刪除時,您可以便宜地計算新的中位數 (它可以是相同的節點,下一個節點或前一個節點,沒有其他選擇)。
請注意,修改此指針是O(1) (盡管插入/刪除本身是O(logn)

鑒於這些知識 - 可以緩存指向中值元素的指針,並確保在刪除/插入時保留它。 當你要求中位數時 - 只需從緩存中取中位數 - O(1)


關於Unsuccessful search - O(1) {With a high likely-hood} - 這個是尖叫blo bloom過濾器 ,這是一個概率集實現,從來沒有假陰性(從來沒有說過某些東西沒有設置),但是一些誤報(說某些東西在緩存中,而事實上並非如此)。

你不需要B + -tree的中位數。 您需要在要拆分的節點中使用中值鍵。 您必須在該中位數處進行拆分以滿足每個節點具有N / 2 <= n <= N個鍵的條件。 節點中的中間密鑰只是中間的密鑰, n / 2 ,其中n是節點中實際密鑰的數量。 這就是你拆分節點的地方。 計算是O(1):它不會傷害運行時。

在不疊加其他數據結構的情況下,您無法從B +樹獲得O(1)搜索失敗時間。

我已經發布了一個答案(並且已經刪除了),但我可能會誤解,所以這里有另一種解釋的答案......

如果您需要始終知道哪個項目是完整 B +樹容器中的中位數,該怎么辦?

正如amit所說,你可以將指針(以及你的根指針)保存到包含中位數的當前葉節點。 您還可以在該葉節點中保留索引。 因此,您可以通過直接跟蹤到正確的節點和項目來獲得O(1)訪問權限。

問題在於維持這一點。 當然amit是正確的,對於每個插入,中位數也必須保持相同的項目,或者必須步驟到之前或之后的那個。 如果您通過葉節點有一個鏈表,即使這意味着步進到相鄰的葉節點,也可以有效地處理。

但是,我不相信,確定是否或采用哪種方式都是微不足道的,除非在中位數和插入恰好位於同一葉節點的特殊情況下。

如果您知道完整樹的大小(可以使用根指針輕松存儲和維護),則至少可以確定插入前后中間項應該在哪個索引處。

但是,如果插入點位於中位數之前或之后,您需要知道先前的中位數項是否已將其指數向上移動。 除非插入點和中位數碰巧在同一節點中,否則這是一個問題。

Overkill方式 - 擴充B +樹以支持計算項目的索引並搜索索引。 其訣竅是每個節點保留其子樹的葉節點中的項目總數。 這可以推高一個級別,因此每個分支節點都有一個子樹大小數組及其子節點指針數組。

這提供了兩種解決方案 您可以使用該信息在搜索時確定插入點的索引,或者(提供節點具有父指針)您可以使用它來重新確定插入后的上一個中間項的索引。

[實際上是三個。 插入后,你可以根據新的大小搜索新的中途索引而不參考前面的中間鏈接。]

然而,就存儲用於增強的數據而言,這結果是過度的。 您不需要知道插入點的索引或先前的中位數 - 您可以知道插入的中位數的哪一側。 如果您知道要從根到中間項的跟蹤,您應該能夠在搜索插入點時跟蹤它的哪一側。 因此,您只需要增加足夠的信息來查找和維護該蹤跡。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM