平衡樹學習筆記(1) splay

2021-09-24 23:41:54 字數 2288 閱讀 6629

3.一些廢話

4.不知道是不是廢話的話

==**(中考加油!)**==

​ splay原名伸展樹(splay tree),也叫**樹,是一種二叉排序樹,它能在o(log n)內完成插入、查詢和刪除操作。它由丹尼爾·斯立特(daniel sleator) 和羅伯特·恩卓·塔揚(robert endre tarjan) 在2023年發明的。

​ 伸展樹是一種自調整形式的二叉查詢樹,它會沿著從某個節點到樹根之間的路徑,通過一系列的旋轉把這個節點搬移到樹根去。

新建節點:

int get(int &x,int v,int fa)

讓序列中的第x個數旋轉到根的:

int st(int y,int z)

而在splay裡面,就需要用到雙旋(即對於爺爺,父親和兒子三點共線時,先旋父親,再旋兒子)。

如圖。

圖三

先rotate(y),變為:

圖四

再rotate(x),變為:

圖五

嗯,是這樣吧…

接著就完成了一次雙旋。

然而,對於splay(x,y),我們需要做的是將x旋轉到y的兒子的位置。

所以我們要不斷地旋轉它(x),直到它成為y的兒子。

int splay(int x,int g)

if (!g)

root=x;

}

其實建樹有很多方法,這裡講比較通用的一種。

就是像線段樹一樣從root節點開始,每次分到它的左右兒子去。

int build(int &x,int l,int r,int fa)

當然,還有比較暴力的方法:

1.先建成一條鏈,再通過splay使其盡量平衡。

2.建乙個只有根節點的樹,再不斷插入(insert)節點。

具體視情況而定。

方法一:插入值為x的點,那麼我們可以先找到它的前驅以及後繼,再新建節點,並且將該節點設為前驅和後繼的父親。

方法二:將這個點的前驅設為根,後繼設為根的右兒子,那麼直接在後繼的左兒子處增加這個節點即可。

很好理解吧。

以下**為方法二:

int ins(int x,int y)

由於delete為系統自帶函式,所以改下名。

跟插入的道理其實差不多,將x的前驅旋到更,後繼後繼設為根的右兒子,那麼後繼的左兒子只能為x(證明顯然)。

刪掉就好了。

int del(int x)

其實道理很簡單,就是在splay tree裡找到節點所在的位置,然後直接修改更新就好了。

int replace(int a,int b)

{ int x=root;

a++;

while (size[l]+1!=a)

if (a這個視不同情況而定,很難寫,但是總的來說就是:

比如統計x~y的答案,那麼我們就直接將x旋到根,y的後繼旋到根的左兒子,同理,y的後繼的左子樹即為答案。

splay要盡量打在struct裡,不要問為什麼,常數優化。

對於一些很難維護的東西,要考慮兩點:

是不是可以通過套用其他的演算法或者結構解決。

實在想不到的話,可以先轉化成線段樹式的維護,再通過模擬思想轉移過來。

在維護時,記得該update的地方一定要update(否則正確率擔憂),不該update的地方一定不要update(否則時間擔憂),所以在打splay時一定要考慮清楚了再打。

使用#define可以節省很多**量,也可以節省很多時間。

切記!!!空間一定要開夠,但是不要爆掉!!!必要時可以建乙個棧來存放無用節點,可以節省很多空間。

其實splay也叫spaly…

學習筆記 普通平衡樹Splay

哈哈哈哈哈哈哈終於會打 splay 啦 現在我來發一下 splay 的講解吧 小蒟蒻由於碼風與他人不同,所以自己找了上百篇碼風詭異的 splay 合成的,感謝 zcysky 的 與我碼風相近,讓我看懂了 首先,splay 其實就是把一棵二叉搜尋樹變成一棵深度不會超過 logn 的二叉搜尋樹,它在不斷...

平衡樹學習筆記(3) Splay

splay是乙個實用而且靈活性很強的平衡樹 效率上也比較客觀,但是一定要一次性寫對 debug可能不是那麼容易 splay作為平衡樹,它的平衡方式就是旋轉 暴力旋轉,赤裸裸的旋轉,各種旋轉 就是依靠玄學的旋轉來保證自己的複雜度 不廢話,上主題 struct node 不寫建構函式一時爽,一直不寫一直...

平衡樹之splay

在每次查詢之後對樹進行重構 把被查詢的條目搬移到 離樹根近一些的地方。伸展樹應運而生。伸展樹是一種自調整形式的二叉查詢樹,它會 沿著從某個節點到樹根之間的路徑 通過一系列的旋轉把這個節點搬移到樹根去。大家只需要記住,每次進行插入 查詢的時候,都要把插入 查詢的元素通過旋轉變到根的位置,splay 的...