日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数据结构之Treap

發(fā)布時間:2025/3/21 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构之Treap 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
1. 概述

同splay tree一樣,treap也是一個平衡二叉樹,不過Treap會記錄一個額外的數(shù)據(jù),即優(yōu)先級。Treap在以關(guān)鍵碼構(gòu)成二叉搜索樹的同時,還按優(yōu)先級來滿足堆的性質(zhì)。因而,Treap=tree+heap。這里需要注意的是,Treap并不是二叉堆,二叉堆必須是完全二叉樹,而Treap可以并不一定是。

2. Treap基本操作

為了使Treap 中的節(jié)點同時滿足BST性質(zhì)和最小堆性質(zhì),不可避免地要對其結(jié)構(gòu)進(jìn)行調(diào)整,調(diào)整方式被稱為旋轉(zhuǎn)。在維護(hù)Treap 的過程中,只有兩種旋轉(zhuǎn),分別是左旋轉(zhuǎn)(簡稱左旋)和右旋轉(zhuǎn)(簡稱右旋)。

左旋一個子樹,會把它的根節(jié)點旋轉(zhuǎn)到根的左子樹位置,同時根節(jié)點的右子節(jié)點成為子樹的根;右旋一個子樹,會把它的根節(jié)點旋轉(zhuǎn)到根的右子樹位置,同時根節(jié)點的左子節(jié)點成為子樹的根。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 struct Treap_Node { ??Treap_Node *left,*right; //節(jié)點的左右子樹的指針 ??int value,fix; //節(jié)點的值和優(yōu)先級 }; void Treap_Left_Rotate(Treap_Node *&a) //左旋 節(jié)點指針一定要傳遞引用 { ??Treap_Node *b=a->right; ??a->right=b->left; ??b->left=a; ??a=b; } void Treap_Right_Rotate(Treap_Node *&a) //右旋 節(jié)點指針一定要傳遞引用 { ??Treap_Node *b=a->left; ??a->left=b->right; ??b->right=a; ??a=b; }

3. Treap的操作

同其他樹形結(jié)構(gòu)一樣,treap的基本操作有:查找,插入,刪除等。

3.1??? 查找

同其他二叉樹一樣,treap的查找過程就是二分查找的過程,復(fù)雜度為O(lg n)。

3.2??? 插入

在Treap 中插入元素,與在BST 中插入方法相似。首先找到合適的插入位置,然后建立新的節(jié)點,存儲元素。但是要注意新的節(jié)點會有一個優(yōu)先級屬性,該值可能會破壞堆序,因此我們要根據(jù)需要進(jìn)行恰當(dāng)?shù)男D(zhuǎn)。具體方法如下:

1. 從根節(jié)點開始插入;

2. 如果要插入的值小于等于當(dāng)前節(jié)點的值,在當(dāng)前節(jié)點的左子樹中插入,插入后如果左子節(jié)點的優(yōu)先級小于當(dāng)前節(jié)點的優(yōu)先級,對當(dāng)前節(jié)點進(jìn)行右旋;

3. 如果要插入的值大于當(dāng)前節(jié)點的值,在當(dāng)前節(jié)點的右子樹中插入,插入后如果右子節(jié)點的優(yōu)先級小于當(dāng)前節(jié)點的優(yōu)先級,對當(dāng)前節(jié)點進(jìn)行左旋;

4. 如果當(dāng)前節(jié)點為空節(jié)點,在此建立新的節(jié)點,該節(jié)點的值為要插入的值,左右子樹為空,插入成功。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 Treap_Node *root; void Treap_Insert(Treap_Node *&P,int value) //節(jié)點指針一定要傳遞引用 { ??if (!P) //找到位置,建立節(jié)點 ??{ ????P=new Treap_Node; ????P->value=value; ????P->fix=rand();//生成隨機的修正值 ??} ??else if (value <= P->value) ??{ ????Treap_Insert(P->left,r); ????if (P->left->fix < P->fix) ??????Treap_Right_Rotate(P);//左子節(jié)點修正值小于當(dāng)前節(jié)點修正值,右旋當(dāng)前節(jié)點 ??} ??else ??{ ????Treap_Insert(P->right,r); ????if (P->right->fix < P->fix) ??????Treap_Left_Rotate(P);//右子節(jié)點修正值小于當(dāng)前節(jié)點修正值,左旋當(dāng)前節(jié)點 ??} }

3.3 ? 刪除

與BST 一樣,在Treap 中刪除元素要考慮多種情況。我們可以按照在BST 中刪除元素同樣的方法來刪除Treap 中的元素,即用它的后繼(或前驅(qū))節(jié)點的值代替它,然后刪除它的后繼(或前驅(qū))節(jié)點。

上述方法期望時間復(fù)雜度為O(logN),但是這種方法并沒有充分利用Treap 已有的隨機性質(zhì),而是重新得隨機選取代替節(jié)點。我們給出一種更為通用的刪除方法,這種方法是基于旋轉(zhuǎn)調(diào)整的。首先要在Treap 樹中找到待刪除節(jié)點的位置,然后分情況討論:

情況一,該節(jié)點為葉節(jié)點或鏈節(jié)點,則該節(jié)點是可以直接刪除的節(jié)點。若該節(jié)點有非空子節(jié)點,用非空子節(jié)點代替該節(jié)點的,否則用空節(jié)點代替該節(jié)點,然后刪除該節(jié)點。

情況二,該節(jié)點有兩個非空子節(jié)點。我們的策略是通過旋轉(zhuǎn),使該節(jié)點變?yōu)榭梢灾苯觿h除的節(jié)點。如果該節(jié)點的左子節(jié)點的優(yōu)先級小于右子節(jié)點的優(yōu)先級,右旋該節(jié)點,使該節(jié)點降為右子樹的根節(jié)點,然后訪問右子樹的根節(jié)點,繼續(xù)討論;反之,左旋該節(jié)點,使該節(jié)點降為左子樹的根節(jié)點,然后訪問左子樹的根節(jié)點,這樣繼續(xù)下去,直到變成可以直接刪除的節(jié)點。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 BST_Node *root; void Treap_Delete(Treap_Node *&P,int *value) //節(jié)點指針要傳遞引用 { ??if (value==P->value) //找到要刪除的節(jié)點 對其刪除 ??{ ????if (!P->right || !P->left) //情況一,該節(jié)點可以直接被刪除 ????{ ??????Treap_Node *t=P; ??????if (!P->right) ????????P=P->left; //用左子節(jié)點代替它 ??????else ????????P=P->right; //用右子節(jié)點代替它 ??????delete t; //刪除該節(jié)點 ????} ????else //情況二 ????{ ??????if (P->left->fix < P->right->fix) //左子節(jié)點修正值較小,右旋 ??????{ ????????Treap_Right_Rotate(P); ????????Treap_Delete(P->right,r); ??????} ??????else //左子節(jié)點修正值較小,左旋 ??????{ ????????Treap_Left_Rotate(P); ?????????Treap_Delete(P->left,r); ??????} ????} ??} ??else if (value < P->value) ????Treap_Delete(P->left,r); //在左子樹查找要刪除的節(jié)點 ??else ????Treap_Delete(P->right,r); //在右子樹查找要刪除的節(jié)點 }

4. Treap應(yīng)用

Treap可以解決splay tree可以解決的所有問題,具體參見另一篇博文:《數(shù)據(jù)結(jié)構(gòu)之伸展樹》

可以這樣定義結(jié)構(gòu)體:

1 2 3 4 5 6 7 8 9 10 11 12 13 struct Treap_Node { ??Treap_Node *left,*right; //節(jié)點的左右子樹的指針 ??int value,fix,weight,size; //節(jié)點的值,優(yōu)先級,重復(fù)計數(shù)(記錄相同節(jié)點個數(shù),節(jié)省空間),子樹大小 ??inline int lsize(){ return left ?left->size ?0; } //返回左子樹的節(jié)點個數(shù) ??inline int rsize(){ return right?right->size?0; } //返回右子樹的節(jié)點個數(shù) };

5. 總結(jié)

Treap 作為一種簡潔高效的有序數(shù)據(jù)結(jié)構(gòu),在計算機科學(xué)和技術(shù)應(yīng)用中有著重要的地位。它可以用來實現(xiàn)集合、多重集合、字典等容器型數(shù)據(jù)結(jié)構(gòu),也可以用來設(shè)計動態(tài)統(tǒng)計數(shù)據(jù)結(jié)構(gòu)。

6. 參考資料

(1)Treap:http://www.nocow.cn/index.php/Treap

(2)隨機平衡二叉查找樹Treap 的分析與應(yīng)用:http://www.byvoid.com/blog/wp-content/uploads/2010/12/treap-analysis-and-application.pdf

———————————————————————————————-

更多關(guān)于數(shù)據(jù)結(jié)構(gòu)和算法的介紹,請查看:數(shù)據(jù)結(jié)構(gòu)與算法匯總

———————————————————————————————-

原創(chuàng)文章,轉(zhuǎn)載請注明:?轉(zhuǎn)載自董的博客

本文鏈接地址:?http://dongxicheng.org/structure/treap/

總結(jié)

以上是生活随笔為你收集整理的数据结构之Treap的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。