2015-11-28 13 views
0

我一直在玩Binomial堆,而且我遇到了一個問題,我想在此討論,因爲我認爲它可能會涉及某些用戶實現Binomial Heap數據結構。二項式堆結構不會讓您指向節點(或迭代器)

我的目標是讓指向節點或句柄的指針,它們直接指向Binomial Heap內部節點,當我將它們插入到二項式堆中時,該節點又包含我的優先級值(通常爲整數)。 以這種方式,我將指針/句柄保持爲我所插入的內容,如果是這種情況,我可以使用binomial_heap_delete_node(node)直接刪除值,就像迭代器一樣。

正如我們將看到的,這是不是可能與二項堆,這是因爲這種數據結構的架構。

與二項堆的主要問題是,在某些時候,你需要一個操作:binomial_heap_swap_parent_and_child(parent, child),你就需要在這兩個binomial_heap_decrease_key(node, key)binomial_heap_delete_node(node)此操作。通過閱讀他們的名字,這些操作的目的非常明確。

所以,問題是如何binomial_heap_swap_parent_and_child(parent, child)作品:在所有我看到了實現中,交換節點之間的優先值,節點本身。 這將使節點的所有指針/句柄/迭代器無效,因爲它們仍然指向正確的節點,但這些節點不會具有您之前插入的同一優先級值,而是另一個節點。

如果我們看到Binomial堆(或一般的二叉樹)是如何構造的:這是非常合乎邏輯的:您有一個父節點,被許多孩子視爲「父母」,所以很多孩子指出它,但是那個父節點並不知道有多少個孩子(或者更重要的是哪個孩子)指向它,所以它會是不可能的這樣交換一個節點的位置。你唯一的選擇是交換整數優先級鍵,但是這將使節點的所有指針/句柄/迭代器無效。

注:可能的解決辦法NOT成爲其中代替使用binomial_heap_delete_node(node),一個可以只設置該節點的優先級,以除去到-999999999(或最小值)和彈出的最小節點出來:這不會解決問題,因爲binomial_heap_decrease_key(node, key)仍然需要節點的父子交換操作,而唯一的解決辦法就是交換整數優先級。

我想知道是否有人在此問題之前發生過。 我認爲唯一的解決方案是使用另一個堆結構,比如Binary Heap,Pairing Heap或其他。

回答

0

與許多數據結構問題一樣,用額外的間接級別來解決這個問題並不困難。定義類似於:

struct handle { 
    struct heap_node *node; // points to node that "owns" this handle 
    struct user_data *data; // priority key calculated from this 
} 

您向用戶提供句柄(通過複製或指針/參考;您的選擇)。

每個內部節點只指向一個句柄(即node->handle->node == node)。兩個這樣的指針被交換來交換父母和孩子。

幾種變化是可能的。例如。data字段可能是數據本身,而不是指向它的指針。主要思想是在句柄和節點之間添加間接級別提供了必要的靈活性。

+0

是的,你的解決方案是非常明顯的,就像在每個節點中添加一個指針向量一樣,將指向該節點的指針指向父節點。但是,無論是在每個節點添加更多數據,還是增加更多間接級別,我都會導致性能下降。所以現在,解決方案仍然使用另一個不是二項堆的數據結構。 –

+0

@MarcoPagliaricci我想這很明顯,你沒有提及它;-)。但是你會遇到類似的問題與其他堆。例如。一個簡單的二進制堆,以通常的方式維護爲數組中的完整二叉樹:其中基本實現將數據存儲在數組中,要獲取刪除和減少鍵,必須將指針(或數組索引)存儲在數組中,指的是數據在別處。並且您必須將數據的反轉映射保存到完整的樹形數組中。這是我的一個實現(用於特殊目的):https://github.com/gene-ressler/lulu/blob/master/ext/lulu/pq.c – Gene

+0

@MarcoPagliaricci NB:另一點是我不是確定你的意思是「殺死性能」。仔細實施,您將爲每個節點添加一個指針。這實際上是一種罕見的應用,每個節點4或8個字節和每個訪問的單個指針解引用將導致顯着差異。這正是C++對象引用引入的開銷,例如 – Gene