堆是優先佇列的一種實現方式,堆中父節點大於等於(或小於等於)兩子節點,每次的刪除,查詢,插入都是 o(l
og2n
)o(log_2n)
o(log2
n) 的複雜度
左兒子的dis值大於等於右兒子的dis值
- 定義結束,我們可能要問如何建一棵左偏樹?這裡我要說,左偏樹和傳統的堆不同,沒有pushup操作,左偏樹唯一的操作就是合併merge。 >也就是說,我們建立左偏樹,是將每個節點都看成一棵左偏樹,然後一步一步合併起來的,所以我們要先明確什麼是合併操作。對左偏樹最核心的合併操作,是這樣的(假設數越小優先順序越大):
如此遞迴操作即可在 o(l
og2(
m+n)
)o(log_2(m + n))
o(log2
(m+
n)) 內完成兩個左偏樹的合併
其他操作建立在合併之上,下面是常見的幾種。
模板題 洛谷p3377
**:
#include
#include
#include
#include
using
namespace std;
int n, m;
struct ab
aa[200005];
voidsw(
int& a,
int& b)
bool bk[
100005]=
;int
merge
(int x,
int y)if(
!y)if
(aa[x]
.v > aa[y]
.v ||
(aa[x]
.v == aa[y]
.v && x > y)
) aa[x]
.rs =
merge
(aa[x]
.rs, y)
; aa[aa[x]
.rs]
.fa = x;
if(aa[x]
.ls)
if(aa[aa[x]
.ls]
.dis < aa[aa[x]
.rs]
.dis)if(
!aa[x]
.rs)
else
return x;
}intmn(
int x)
return aa[x]
.fa;
}int
main()
for(
int i =
1; i <= m;
++i)
merge(mn
(xx),mn
(yy));
}else
else}}
return0;
}
總之,沒有完美的資料結構。但左偏樹確實好寫,不想用堆了(直接用平板電視更容易) 左偏樹(可並堆)
左偏樹其實是一種可並堆,它可以 o log2 n o l og2n 合併兩個堆。那左偏?也就是說他左邊肯定有什麼東西比右邊大 別著急,在左偏樹上有乙個叫距離的東西 個點的距離,被定義為它子樹中離他最近的外節點到這個節點的距離 這與樹的深度不同 其中我們定義乙個節點為外節點,當且僅當這個節點的左子樹和...
可並堆 左偏樹
題目描述 如題,一開始有n個小根堆,每個堆包含且僅包含乙個數。接下來需要支援兩種操作 操作1 1 x y 將第x個數和第y個數所在的小根堆合併 若第x或第y個數已經被刪除或第x和第y個數在用乙個堆內,則無視此操作 操作2 2 x 輸出第x個數所在的堆最小數,並將其刪除 若第x個數已經被刪除,則輸出 ...
可並堆 左偏樹 斜堆
經典的二叉堆已經可以在 o log n 的複雜度的情況下維護堆這樣的資料結構,也有d 堆可以維護成 o log d n 雖然pop操作的複雜度是 o d log d n 然而這兩種堆不能滿足 o log n 的合併操作,它們的經常是 o n log n 即每次將乙個堆中的堆頂拿出來放到另乙個堆裡。雖...