優先佇列之 二項堆

2021-06-29 15:42:57 字數 3455 閱讀 3953

從以上定義,不難得到下面的結論:

二項堆由一組二項樹所構成,這裡的二項樹需要滿足下列條件:

1)h中的每個二項樹遵循最小堆的性質。

2)對於任意非負整數k,在h中至多有一棵二項樹的根具有度數k。

對於性質2,任意高度最多有一棵二項樹,這樣就可以用二項樹的集合唯一地表示任意大小的二項堆,比如13個結點的二項堆h,13的二進位制表示為(1101),故h包含了最小堆有序二項樹b3, b2和b0, 他們分別有8, 4, 2, 1個結點,即共有13個結點。如下圖(另外:二項堆中各二項樹的根被組織成乙個鍊錶,稱之為根表)

}由於每乙個二項樹都滿足最小堆的性質,所以每個二項樹的最小關鍵字一定在根結點,故只需遍歷比較根表的情況就可以。

binheap findbinheapmin(binheap heap)

}return min_node;

}

合併兩個二項堆有三個函式:

binomial-pair,連線操作,即將兩棵根節點度數相同的二項樹bk-1連線成一棵bk。

binomial-heap-merge ,將h1和h2的根表合併成乙個按度數的單調遞增次序排列的鍊錶。

binomial-heap-union,反覆連線根節點的度數相同的各二項樹。

合併操作分為兩個階段:

第一階段:執行binomial-heap-merge,將兩個堆h1和h2的根表合併成乙個鍊錶h,它按度數排序成單調遞增次序。merge的時間複雜度o(logn)。n為h1和h2的結點總數。(對於每乙個度數值,可能有兩個根與其對應,所以第二階段要把這些相同的根連起來)。

第二階段:將相等度數的根連線起來,直到每個度數至多有乙個根時為止。執行過程中,合併的堆h的根表中至多出現三個根具有相同的度數。(merge後h中至多出現兩個根具有相同的度數,但是將兩個相同度數的根的二項樹連線後,可能與後面的至多兩棵二項樹出現相同的度數的根,因此至多出現三個根具有相同的度數)

第二階段根據當前遍歷到的根表中的結點x,分四種情況考慮:

case1:degree[x] != degree[sibling[x]]。此時,不需要做任何變化,將指標向根表後移動即可。(下圖示a)

case2:degree[x] == degree[sibling[x]] == degree[sibling[sibling[x]]]。此時,仍不做變化,將指標後移。(下圖示b)

case3 & case4:degree[x] = degree[sibling[x]] != degree[sibling[sibling[x]]] (下圖示c和d)

case3:key[x] <= key[sibling[x]]。此時,將sibling[x]連線到x上。

case4:key[x] > key[sibling[x]]。此時,將x連線到sibling[x]上。

複雜度:o(logn), 四個過程變化情況:

//********************===兩個二項佇列的連線*************************===

binheap binheapunion(binheap h1, binheap h2)

//case 3、4:相鄰2個相等,和第3個不等

else

//case 4: 將x連到x_next

else

}//case 3&4

x_next = x->sibling;

}//while

return heap;

}//將2個二項佇列合併成度數單調遞增的乙個二項佇列

binheap binheapmerge(binheap h1, binheap h2)

else

if(h3_prev ==

null)

else

}//while

if(h1 ==

null)

h3_prev->sibling = h2;

else

if(h2 ==

null)

h3_prev->sibling = h1;

}if(h1 ==

null)

if(h2 ==

null)

return heap;

}//連線2個度數k相同的二項樹成度數為k+1的一棵樹,將h1 連線到 h2上

先建立只有該結點的二項堆,然後在與原來的二項堆合併。

//用陣列元素建立二項佇列

binheap creatheapwitharray(item a, int n)

memset(newheap, 0, sizeof(*newheap));

newheap->key = a[i];

if(heap == null)

heap = newheap;

else

}return heap;

}

從根表中找到最小關鍵字的結點,將以該結點為根的整棵二項樹從堆取出,刪除取出的二項樹的根,將其剩下的子女倒序排列,組成了乙個新的二項堆,再與之前的二項堆合併。

binheap binheapdelmin(binheap h1)

p = p->sibling;

}binheap heap = h1;

if(h1 ==

min)

heap =

min->sibling;

else

min_prev->sibling =

min->sibling;

binheap x_prev =

null, x =

null; //

binheap h2 =

null;

p =null;

x =min->leftchild;

while (x !=

null)

heap = binheapunion(heap, h2);

return

min;

}

優先佇列 堆 二項佇列

目錄四 二項佇列的實現 位址 我們知道,左式堆每次操作的時間界是 o logn 二項佇列支援合併 插入 刪除最小值,每次插入的平均時間為常數時間,而最壞時間是 o logn 二項佇列 結構 高度為0的二項樹是一棵單節點樹,例如b0。高度為k的二項樹 b k 通過將一棵二項樹 b 附接到另一棵二項樹 ...

優先佇列《堆》

1.模型 兩個基本操作 insert等價enqueue deletemin刪除最小者 dequeue 2.簡單的實現 1 簡單鍊錶 遍歷刪除min或者排序刪除min 2 使用二叉查詢樹。反覆除去min會使得樹不平衡,並且bst還支援許多不需要的操作。3.二叉堆 優先佇列的實現普遍使用二叉堆,堆有兩個...

優先佇列 堆

印表機列印作業一般是放在佇列中的。如果按照先來先列印的順序,有乙個100頁的列印任務,那麼會讓後面短小的任務等待很長時間。更合理的做法也許是最後處理最耗時的列印任務,不管它是不是最後提交上來的。在多使用者作業系統中,作業系統讓哪個程式使用cpu,是需要決定從佇列裡面選擇的。一般做法是從隊頭獲得程式,...