我們曾經學習過基礎資料結構之一——堆(heap)
堆支援三種操作(以小根堆為例)
1、查詢(query):查詢堆中最小的元素
2、刪除(del):刪除堆中的任意乙個元素
3、插入(insert):插入乙個新元素
4、維護(modify):維護堆的性質:任何非葉子結點的權值都大於它的所有子結點。在刪除和插入後進行維護
如果題目要求我們將兩個不相關但型別相同(都是大根對或小根堆)的堆合併成乙個大堆,我們就用到了左偏樹。
child[i][0]和child[i][1]是左右結點的指標,val[i]是當前結點的權值,dis[i]是當前結點的距離標號,fa[i]該結點的父節點
距離標號:當前結點到離它最近的葉子節點的距離
(1)、節點的權值小於等於它左右兒子的權值。
和堆的性質相同
(2)、節點的左兒子的距離不小於右兒子的距離。
這就是為什麼這棵樹叫做左偏樹,也就是左邊的結點總數始終大於或等於右邊孩子的結點總數
在寫平衡樹的時候,我們是確保它的深度盡量的小,這樣訪問每個節點都很快。但是左偏樹不需要這樣,它的目的是快速提取最小節點和快速合併。所以它並不平衡,而且向左偏。但是距離和深度不一樣,左偏樹並不意味著左子樹的節點數或是深度一定大於右子樹。
**(3)、節點的距離等於右兒子的距離+1。
(4)、乙個n個節點的左偏樹距離最大為 log(n+1)-1
證明如下:
若左偏樹的距離為一定值,則結點數最少的左偏樹是完全二叉樹。
結點最少的話,就是左右兒子距離一樣,這就是完全二叉樹了。
若一棵左偏樹的距離為k,則這棵左偏樹至少有 2^-1個節點。
距離為k的完全二叉樹高度也是k,節點數就是 2^-1個。
這樣就可以證明性質四了。
因為 n>=2^-1,所以 k<=log(n+1)-1。
現在有兩個小根堆a,b,要將他們合併
1、如果a根結點的權值大於b根結點,便交換a,b,保證接下來操作時a根結點的權值小於或等於b根結點。
2、把a結點的根結點作為兩樹合併後的新樹c的根結點
3、合併a的右子樹和b堆,因為左偏樹的左子樹較重,所以為了維持操作時間複雜度為o(logn),所以合併a的右子樹和b堆。
4、合併了a的右子樹和b之後,a的右子樹的距離可能會變大,當a的右子樹的距離大於a的左子樹的距離時,性質2會被破壞。在這種情況下,我們只須要交換a的右子樹和左子樹。
而且因為a的右子樹的距離可能會變,所以要更新a的距離標號。這樣就合併就結束了。
再理解一下**:
int merge (int x,int y)
int get_rt (int x)
void del (int x)
int main()
} else
}} return 0;
}
資料結構 左偏樹
今天學了左偏樹,看了一天,一些細節還是不太明白。有點混亂。做題的時候也不是很明白方法。先來介紹左偏樹 見 資料結構 9 左偏樹 見例題 判斷是否認識,並查集。因為要用到合併,而且輸出最強壯值,二叉堆不能合併,所有要用到能夠合併的資料結構 左偏樹。這題能夠好好理解左偏樹的實現方法。include in...
資料結構 左偏樹
題目描述 如題,一開始有n個小根堆,每個堆包含且僅包含乙個數。接下來需要支援兩種操作 操作1 1 x y 將第x個數和第y個數所在的小根堆合併 若第x或第y個數已經被刪除或第x和第y個數在用乙個堆內,則無視此操作 操作2 2 x 輸出第x個數所在的堆最小數,並將其刪除 若第x個數已經被刪除,則輸出 ...
資料結構入門7 左偏樹
一種可並堆,具有左偏性質。每個點有乙個距離。距離則是如下定義的 節點i稱為外節點 externalnode 當且僅當節點i的左子樹或右子樹為空 left i null或right i null 節點i的距離 dist i 是節點i到它的後代中,最近的外節點所經過的邊數。特別的,如果節點i本身是外節點...