平衡樹學習筆記(3) Splay

2022-07-20 04:39:09 字數 3153 閱讀 6258

splay是乙個實用而且靈活性很強的平衡樹

效率上也比較客觀,但是一定要一次性寫對

debug可能不是那麼容易

splay作為平衡樹,它的平衡方式就是旋轉

暴力旋轉,赤裸裸的旋轉,各種旋轉

就是依靠玄學的旋轉來保證自己的複雜度

不廢話,上主題

struct node    //不寫建構函式一時爽,一直不寫一直爽~~~

bool isr() //當前點是否為父親右孩子,旋轉的時候用,方便

int rk() //當前的排名

void upd() //維護資訊

}pool[maxn], *tail, *root, *st[maxn]; //記憶體池與**池,還有根節點

其實這個就是第一節說的旋轉

rot(x)代表把x轉到它父親的位置上去

這也是splay維護平衡的基礎

下面是重點了!!

把x轉到它父親y上

以下**中字母對應,其中那個r是**中的w(因為為中間量,要特殊對待)

void rot(node *x)
以上部分一定要理解透徹!!!這個操作使基於rotate的

splay(x),作用是把x轉到根節點的位置上

顯然要轉好多次的qwq

因為一些玄學的東西(霧

平衡樹中,每次用到誰轉誰(反正不影響性質,說白了貌似還是瞎轉)

這樣玄學的操作可以使splay平衡

void splay(node *x) 

}

上面if那一行是啥意思呢?

我們要考慮一條鏈的情況

這種情況我們要先轉父親,再**己

否則直接**己就行

至此,基本操作已經結束qwq

這個是真的暴力插。。。。。。

void ins(int val) 

//跳到了空節點上,那麼申請新節點

o = new(top? st[top--] : tail++) node(fa, val, 1);

fa->ch[val > fa->val] = o;

//玄學操作,轉上去

splay(o);

}

這個有點。。鬼畜

一般來說,(我所知道的)有兩種刪除方式,某崔性男子說可以merge(霧

第一種找到要刪節點的前驅和後繼

前驅轉到根,後繼轉到根的右孩子

r的左子樹一定是我們要刪的,直接刪就行了(父子不互認,其他變數清空)

第二種需要兩個函式(好像有點麻煩吧qwq)

node *lst()
返回根的前驅

下面的是真正的刪除

首先把要刪的節點轉到根並記錄一下

找到根的前驅

把根的前驅轉到根

那麼一定是這種情況

原根,也就是要刪的點,一定是沒有左孩子的!!!!

所以類似於鍊錶的操作,把該刪的刪掉

inline void del(int x)
暴力找
int rnk(int val) 

return splay(lst), rank + 1;

}

其實跟上面差不多
int kth(int k) 

return splay(o), o->val;

}

這兩個為什麼一塊寫?

因為他們幾乎一樣

int pre(int val) 

return lst->val;

}int nxt(int val)

return lst->val;

}

至此,splay完

其實只要理解了,並不是想象那麼難的

放一下完整**

#include#define ll long long

ll in()

const int maxn = 1e5 + 100;

struct splay

bool isr()

int rk()

void upd()

}pool[maxn], *tail, *root, *st[maxn];

int top;

void rot(node *x)

void splay(node *o)

}node *merge(node *x, node *y, node *fa)

public:

splay()

int rnk(int val)

return splay(lst), rank + 1;

}int kth(int k)

return splay(o), o->val;

}void ins(int val)

o = new(top? st[top--] : tail++) node(fa, val, 1);

fa->ch[val > fa->val] = o;

splay(o);

}void del(int val)

if(!o) return;

splay(o);

root = merge(o->ch[0], o->ch[1], null);

st[++top] = o;

}int pre(int val)

return lst->val;

}int nxt(int val)

return lst->val;

}}v;int main()

return 0;

}

學習筆記 普通平衡樹Splay

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

平衡樹學習筆記(1) splay

3.一些廢話 4.不知道是不是廢話的話 中考加油!splay原名伸展樹 splay tree 也叫 樹,是一種二叉排序樹,它能在o log n 內完成插入 查詢和刪除操作。它由丹尼爾 斯立特 daniel sleator 和羅伯特 恩卓 塔揚 robert endre tarjan 在1985年發明...

平衡樹之splay

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