左傾堆的定義
左傾堆是一棵二叉樹,它的節點除了和二叉樹的節點一樣具有左右子樹指標外,還有兩個屬性:鍵值和零距離。
![左傾堆以及Java實現](https://i.iter01.com/images/5fabb1e9061c9fb4438dbbc2aecc7a5f44a9f417ff0f59883875c5a4c92b7b08.jpg)
- 鍵值的作用是來比較節點的大小,從而對節點進行排序。
- 零距離(英文名NPL,即Null Path Length)則是從一個節點到一個"最近的不滿節點"的路徑長度。不滿節點是指該該節點的左右孩子至少有有一個為NULL。葉節點的NPL為0,NULL節點的NPL為-1。
基本性質
- 節點的鍵值小於或等於它的左右子節點的鍵值。
- 節點的左孩子的NPL >= 右孩子的NPL。
- 節點的NPL = 它的右孩子的NPL + 1。
- 節點的NPL值等於其右子節點的NPL值 + 1
- 左傾堆的左右子節點及其下方節點構成的堆也分別都是左傾堆
合併兩個左傾堆
- 如果一個空左傾堆與一個非空左傾堆合併,返回非空左傾堆。
- 如果兩個左傾堆都非空,那麼比較兩個根節點,取較小堆的根節點為新的根節點。將"較小堆的根節點的右孩子"和"較大堆"進行合併。
- 如果新堆的右孩子的NPL > 左孩子的NPL,則交換左右孩子。
- 設定新堆的根節點的NPL = 右子堆NPL + 1
/**
* 合併
*
* @param x
* @param y
* @return
*/
private LeftistNode<T> merge(LeftistNode<T> x, LeftistNode<T> y) {
if (x == null)
return y;
if (y == null)
return x;
//x結點比y結點大
if (x.key.compareTo(y.key) > 0) {
LeftistNode<T> temp = y;
y = x;
x = temp;
}
x.right = merge(x.right, y);
if (x.left == null || x.left.npl < x.right.npl) {
LeftistNode<T> tmp = x.right;
x.right = x.left;
x.left = tmp;
}
if (x.right == null || x.left == null)
x.npl = 0;
else
x.npl = (x.left.npl < x.right.npl) ? x.left.npl + 1 : x.right.npl + 1;
return x;
}
public void merge(LeftistHeap<T> other) {
merge(mRoot, other.mRoot);
}
複製程式碼