平衡樹SPLAY

一個比線段樹代碼還要又臭又長的數據結構,各式各樣的函數,咱也不知道別人怎么記住的,咱也不敢問

SPLAY的性質

1.某個節點的左子樹全部小于此節點,右子樹全部大于此節點

2.中序遍歷splay輸出的序列是按從小到大的順序

(我當時忽略了性質2,以為大小關系只存在于單獨的左右兒子和父節點,后來問了同學才知道,我沒看過二叉排序樹,我能怎么辦

詢問左右兒子

就是查詢一下x是fa的左兒子還是右兒子

int get(int x)
{return a[a[x].fu].son[1]==x; 
}

?

更新數據

由于每次翻轉之后左右兒子的信息都會改變,所以需要更新一下size

void gx(int x)
{a[x].size=a[a[x].son[0]].size+a[a[x].son[1]].size+a[x].js;
}

?

上旋

什么是上旋呢,簡單來說就是兒子想當爹,然后他還成功了,也不知道這個爹會不會被氣死,就是把自己父節點變成自己的一個兒子,但是對于一個有兩個子節點的子節點,顯然父節點沒地方去,又因為需要保證平衡樹的性質(左子樹小于父節點小于右子樹),所以肯定子節點的某一個葉節點要去給父節點當兒子,根據splay性質中的大小關系,如果子節點是父節點的左兒子那父節點就要去當子節點的右兒子,此時根據splay的性質直接讓子節點的右兒子去當父節點的左兒子即可,這樣就完成了一次翻轉并且沒有改變splay的性質,若子節點是父節點的右兒子,同理交換兒子,總結一下就是假設右旋x,x是fa的0兒子就讓x的1兒子去當fa的0兒子,fa變成x的1兒子(0和1就是一個左一個右)

void sx(int x)
{int f=a[x].fu,ff=a[f].fu;int z1=get(x),z2=get(f);a[f].son[z1]=a[x].son[z1^1];  a[a[x].son[z1^1]].fu=f;a[x].son[z1^1]=f;  a[f].fu=x;a[ff].son[z2]=x;  a[x].fu=ff;gx(f);  gx(x);
}

?

雙旋

我覺得雙旋就是上旋中的一種特殊情況,就是子節點,父節點,祖父節點在同一條線上,這時需要先上旋父節點(據說直接上旋慢,不夠優秀,而且雙旋好像還可以減小期望深度,我并沒有模擬),同一條線的話,特判一下就可以了,記得更新根節點

void splay(int x,int mb)
{while(a[x].fu!=mb){int f=a[x].fu,ff=a[f].fu;int z1=get(x),z2=get(f);if(ff!=mb){if(z1==z2)  sx(f);else  sx(x);}sx(x);}if(mb==0)  root=x;
}

?

幾個基本操作

1.插入節點

插入的話,我覺得和權值線段樹那種遞歸的原理差不多,遍歷來找到合適的位置,加入已經有這個點就直接cnt++,如果沒有的話就新建一個節點,新建之后的話把新建的點旋到根維護下樹就可以了

void cr(int x)
{int dq=root,f=0;while(a[dq].w!=x&&dq!=0){f=dq;dq=a[dq].son[a[dq].w<x];}if(dq!=0)  {a[dq].js++;  gx(dq);}else{dq=++num;if(f!=0)  a[f].son[a[f].w<x]=dq;a[dq].size=1;  a[dq].js=1;a[dq].fu=f;  a[dq].w=x;}splay(dq,0);
}

?

2.刪除結點

刪除還是和插入一樣,有兩種情況,如果這個節點的個數不為一直接cnt--,然后旋到根,如果為一的話刪除這個點又不能影響其他點,但是你沒辦法保證刪除的每一個點都沒有葉子節點,這個時候就需要上旋來保證刪除的點沒有葉子結點,具體操作就是把前驅旋到根,后繼旋到前驅下面,這樣的話被刪除的點就變成了葉子節點,直接清零刪除就可以了

void sc(int x)
{int qqq=qq(x),hjh=hj(x);splay(qqq,0);  splay(hjh,qqq);int z=a[hjh].son[0];if(a[z].js>1)  {a[z].js--;  gx(z);  splay(z,0);}else  a[hjh].son[0]=0;
}

?

3.查詢某值排名

查詢排名先要找到這個值在樹中的位置,當然如果沒有這個值的話會一直找的葉子節點(也不一定是最接近查詢值的點,我運行了一下,發現他會找到第一個比這個值小的值,而不是最接近這個數的值),這種操作的話可以搜極大值和極小值來找到樹中最大值和最小值,找到這個值之后就簡單了,把這個值上旋到根的位置,他左邊都是比他小的,右邊都是比他大的,那么他左子樹的size+1就是這個值的排名

int find(int x)
{int dq=root;while(a[dq].w!=x&&a[dq].son[a[dq].w<x]!=0)dq=a[dq].son[a[dq].w<x];return dq;    
}
int cpm(int x)
{splay(find(x),0);return a[a[root].son[0]].size;
}

?

關于find函數的運行結果(1為插入2為find查詢)

4.查詢某值的前驅/后繼

x的前驅:小于x的最大的數 ???x的后繼:大于x的最小的數

用find函數查找x,把x上旋到根的位置,由于x可能不存在,而find查到的又是第一個比他小的值,所以有可能上旋后根節點就是要查詢的前驅,所以要特判,但是根據我的運行結果來說,我認為后繼不需要特判,如果怕不保險,特判也無所謂,反正特判應該是肯定對的那個,如果有x這個值那么前驅就是他的左子樹的最右葉子節點,同理,后繼就是他右子樹的最左葉子節點,一直向下搜就可以了

int qq(int x)
{splay(find(x),0);int dq=root;if(a[dq].w<x)  return dq;dq=a[dq].son[0];while(a[dq].son[1]!=0)  dq=a[dq].son[1];return  dq;
}
int hj(int x)
{splay(find(x),0);int dq=root;if(a[dq].w>x)  return dq;dq=a[dq].son[1];while(a[dq].son[0]!=0)  dq=a[dq].son[0];return dq;
}

?

5.查詢第k小值

跟主席樹求第k小有點相似,通過記錄左右子樹包含的元素個數與k進行比較,選擇暴力遞歸左兒子或者右兒子,如果當前節點的左子樹元素個數小于k,那么第k小就在右子樹中,k減去左子樹元素個數+當前點的cnt值(還有這個元素自己)后暴力搜索右子樹,如果左子樹元素個數大于k,直接搜索左子樹,假如k介于左子樹右子樹的size之間(一定要想清為什么有范圍,因為同一個值可能出現多次,導致他自己代表的值就不唯一,我死在這好久),那么當前點就是第k小

int csz(int x)
{int dq=root;while(1){int ls=a[dq].son[0];if(a[ls].size>=x)  dq=ls;else if(a[ls].size+a[dq].js<x){x-=a[ls].size+a[dq].js;dq=a[dq].son[1];}else  return a[dq].w;}
}

?

到此,普通平衡樹就可以搞定了

關于插入結點那一塊,雖然最后的splay執行中會更新結點,但是我還是覺得在直接更新cnt之后更新一下節點信息比較好

現在思路是理出來了,也不知道代碼能不能打下來(我依舊是個蒟蒻)

第一次完整的整理了一個知識點還有點興奮

轉載于:https://www.cnblogs.com/hzjuruo/p/11110279.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/274838.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/274838.shtml
英文地址,請注明出處:http://en.pswp.cn/news/274838.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

POJ 2696 計算表達式的值

時間限制: 1000ms內存限制:65536kB描述有些語言中表達式的運算符使用字符串表示&#xff0c;例如用mul代表*&#xff0c;用div代表/&#xff0c;用add代表&#xff0c;用sub代表-&#xff0c;用mod代表%。輸入第一行為表達式的個數n。其余n行每行一個表達式&#xff0c;表達式由…

為支持兩個語言版本,我基于谷歌翻譯API寫了一款自動翻譯的 webpack 插件

大家好&#xff0c;我是若川。持續組織了6個月源碼共讀活動&#xff0c;感興趣的可以點此加我微信 ruochuan12 參與&#xff0c;每周大家一起學習200行左右的源碼&#xff0c;共同進步。同時極力推薦訂閱我寫的《學習源碼整體架構系列》 包含20余篇源碼文章。歷史面試系列本文來…

全球 化 化_全球化設計

全球 化 化重點 (Top highlight)Designing for a global audience can feel daunting. Do you localize your product? Or, do you internationalize your product? And what does that even entail?為全球觀眾設計可能會令人生畏。 您是否將產品本地化&#xff1f; 還是您將…

springMVC_數據的處理過程

1、DispatcherServlet&#xff1a;作為前端控制器&#xff0c;負責分發客戶的請求到 Controller 其在web.xml中的配置如下&#xff1a; <servlet><servlet-name>dispatcherServlert</servlet-name><servlet-class>org.springframework.web.servlet.Dis…

面試體驗:Facebook 篇(轉)

http://www.cnblogs.com/cathsfz/archive/2012/11/05/facebook-interview-experience.html 2012-11-05 08:20 by Cat Chen, 23266閱讀, 121評論, 收藏, 編輯 Google、Microsoft 和 Yahoo 都是去年的事情了&#xff0c;接下來說說今年…

JavaScript 新增兩個原始數據類型

大家好&#xff0c;我是若川。持續組織了6個月源碼共讀活動&#xff0c;感興趣的可以點此加我微信 ruochuan12 參與&#xff0c;每周大家一起學習200行左右的源碼&#xff0c;共同進步。同時極力推薦訂閱我寫的《學習源碼整體架構系列》 包含20余篇源碼文章。歷史面試系列JavaS…

axure低保真原型_如何在Google表格中創建低保真原型

axure低保真原型Google Sheets is a spreadsheet, just like Microsoft Excel.Google表格是一個電子表格&#xff0c;就像Microsoft Excel一樣。 Most people associate it with calculating numbers. But Google Sheets is actually great for organizing your ideas, making…

Weblogic EJB 學習筆記(3)精

編輯實體bean的高級課程 1. 怎樣開發主健類 ejb的主健類主要用做持久存儲和ejb容器中的唯一標識符. 通常主健類的字段直接映射到數據庫中的主健字段. 如果主健只是由單個實體bean字段組成.且其數據類型是基本的java類.如string,則bean作者不必開發自定義的主健類. 只需要在配置…

Lerna 運行流程剖析

大家好&#xff0c;我是若川。持續組織了6個月源碼共讀活動&#xff0c;感興趣的可以點此加我微信 ruochuan12 參與&#xff0c;每周大家一起學習200行左右的源碼&#xff0c;共同進步。同時極力推薦訂閱我寫的《學習源碼整體架構系列》 包含20余篇源碼文章。歷史面試系列Lerna…

手動創建線程池 效果會更好_創建更好的,可訪問的焦點效果

手動創建線程池 效果會更好Most browsers has their own default, outline style for the :focus psuedo-class.大多數瀏覽器對于&#xff1a;focus psuedo-class具有其默認的輪廓樣式。 Chrome’s default outline styleChrome瀏覽器的默認輪廓樣式 This outline style is cr…

C++builder enum類型

C/C code #pragmaoption push -b-enumTThreadPriority { tpIdle, tpLowest, tpLower, tpNormal, tpHigher, tpHighest, tpTimeCritical }; //這是字節型的.理論上說這是可能的最小整形.可以是1Byte, 2Bytes, 4Bytes...#pragmaoption pop#pragmaoption push -benumTThreadPriori…

chrome瀏覽器世界之窗瀏覽器的收藏夾在哪?

今天心血來潮&#xff0c;用一個查重軟件刪除重復文件&#xff0c;結果把chrome瀏覽器和世界之窗瀏覽器的收藏夾給刪除了&#xff0c;導致我保存的好多網頁都沒有了&#xff0c;在瀏覽器本身和網上都沒有找到這兩個瀏覽器默認的收藏夾在哪個位置&#xff0c;只好用DiskGenius 把…

Vue3究竟好在哪里 等推薦

話不多說&#xff0c;這一次花了幾小時精心為大家挑選了30余篇好文&#xff0c;供大家閱讀學習&#xff0c;提升自己的技術視野以及擴展自己的知識儲備。本文閱讀技巧&#xff0c;先粗看標題&#xff0c;感興趣可以都關注一波&#xff0c;一起共同進步。前端從進階到入院框架原…

eazy ui 復選框單選_UI備忘單:單選按鈕,復選框和其他選擇器

eazy ui 復選框單選重點 (Top highlight)Pick me! Pick me! No, pick me! In today’s cheat sheet we will be looking at selectors and how they differ. Unlike most of my other cheat sheets, this will focus on two components (radio buttons and checkboxes) side by…

過濾詞

<?xml version"1.0" encoding"GB2312"?>-<wordList> <word>,</word> <word>.</word> <word><</word> <word>></word> <word>?</word> <word>/</word> <…

VS2010 VC Project的default Include設置

http://blog.csdn.net/jeffchen/article/details/5491435 VS2010與以往的版本一個最大的不同是&#xff1a;VC Directory設置的位置和以前的版本不一樣。VS2010之前&#xff0c;VC Directory的設置都是在IDE的Tools->Options中設置的&#xff1b;VS2010改為&#xff0c;分別…

初級中級高級_初級職位,(半)高級職位

初級中級高級As a recent hire at my new job, as expected, a lot of things seemed scary and overwhelming. The scariest part was not the unfamiliarity with certain tasks or certain tools, but in communicating with higher-level coworkers, managers and bosses. …

如何寫好技術文章(看張鑫旭老師的直播總結

大家好&#xff0c;我是若川。持續組織了6個月源碼共讀活動&#xff0c;感興趣的可以點此加我微信 ruochuan12 參與&#xff0c;每周大家一起學習200行左右的源碼&#xff0c;共同進步。同時極力推薦訂閱我寫的《學習源碼整體架構系列》 包含20余篇源碼文章。歷史面試系列本文是…

Fact Table and Dimension Table In My Opinion

23轉載于:https://www.cnblogs.com/answeryou/archive/2012/05/10/2495122.html

iOS 流媒體 基本使用 和方法注意

項目里面需要添加視頻方法 我自定義 選用的是 avplayer 沒選擇 MediaPlayer 原因很簡單 , avplayer 會更容易擴展 有篇博客 也很好地說明了 使用avplayer的優越性 blog.csdn.net/think12/article/details/8549438在iOS開發上&#xff0c;如果遇到需要播放影片&#xff0c;…