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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

AVL树学习总结

發布時間:2024/7/5 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 AVL树学习总结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

AVL樹

平衡二叉樹的缺點
由于平衡二叉搜索樹的search(), insert(),remove()接口的運行時間與二叉樹的高度成正比,所以若不能有效控制樹高, 從平均復雜度來看,二叉平衡搜索樹并不能讓人滿意

理想平衡
二叉樹的性能取決于樹的高度,只有當左右子樹的高度接近時才能達到理想平衡, 高度為o(logn); 就比如完全二叉樹與滿二叉樹

AVL樹
由于從平常狀態轉變為理想狀態下,所耗費的資源較多, 所以就設定適度的平衡標準, 就此提出AVL樹, AVL樹可保證樹的高度始終保持在O(logn)內
AVL樹的平衡標準: 任一節點都具有平衡因子(其值balFac(v)= height(lc(v)) - height(rc(v)) )的絕對值不能超過1
AVL繼承平衡二叉搜索樹, 對search(), insert(), remove()接口進行重寫

//以下宏定義用于簡化節點的平衡性判斷 //stature表示當前節點的高度 #define Balanced(x)(stature((x).lChild) == stature((x).rChild)))//理想狀態 #define BalFac(x)(stature((x).lChild) - stature((x).rChild))//平衡因子 #define AVBalanced(x) ((-2<BalFac(x)) && (BalFac(x)<2 ))//AVL樹條件

注:空樹的高度取-1, 單節點子樹高度取0
例: 如圖所示節點的平衡因子(皆為左子樹高度-右子樹高度)

節點的插入以及刪除都將影響節點的平衡度

重平衡
在插入x后, AVL失衡, 可沿x出發向上尋找首次出現失衡的節點, 將其確定為祖父節點(g(x)),然后根據g(x),找到g(x)的兒子節點, 孫子節點, 將其設置為p,v, 由于原樹為平衡的,所以在整個向上查找g的過程只需O(logn)的時間 ; 針對g, p, v三個節點的位置進行zig(順時針旋轉節點,使后代上升為父節點), zag(逆時針)旋轉,用于重平衡

//將確定p, v的過程寫為宏定義; //根據插入過程不平衡的出現可得查找原則:左右孩子取高度更高的為p,左右孩子等高,取父親同側,v同上 //根據上圖可知2為g,p為-1,v為1 #define tallerChild(x) ( stature((x)->lChild)>stature((x)->rChild))?(x)->lChild:( (stature((x)->rChild)>stature((x)->lChild))?(x)->rChild:((x->parent->lChild)?x->lChild:x->rChild))) //每一層的比較對應著查找p,v

單旋: 只執行zig/zag旋轉,且執行一次
雙旋: 旋轉過程中即包含zig又包含zag

//zig簡述 g(x)->lChild=p->rChild; p->Child->parent=g(x);//將孩子節點旋轉 p->parent=g(x)->parent; g(x)->parent=p;//將父節點旋轉 //zag原理同上

插入過程中的重平衡
當節點x插入后, 可能導致二叉樹結構一系列節點發生不平衡現象(也就是重心偏向一邊), 但是經過局部旋轉后將可能導致一系列的恢復平衡

刪除過程中的重平衡
當節點x刪除后, 只會導致局部的節點發生不平衡現象, 當對局部的不平衡進行zig/zag調整時, 局部子樹的高度將有可能降低,又有可能導致上一層的祖先發生不平衡,因此需要不斷向上遍歷,發現一個失衡的祖先則將其旋轉至平衡狀態,直到更新到沒有出現不平衡現象

統一重平衡算法
在刪除與插入的過程中都涉及到zig,zag旋轉,于是可將插入,刪除操作統一,為避免通過zig,zag旋轉出現的繁瑣,于是提出了3+4重構的方式
3+4重構: 直接傳入g,p,v三個節點以及這三個節點對應的左右子樹,對其進行全部重新連接,由此可覆蓋所有的旋轉操作

template<typename T>BinNodePosi* BST<T>::connect34(BinNodePosi* a,BinNodePosi* b,BinNodePosi* c, BinNodePosi* T0,BinNodePosi* T1,BinNodePosi* T2,BinNodePosi* T3){a->lChild=T0; if(T0) T0->parent=a;a->rChild=T1; if(T1) T1->parent=a;updateHeight(c);//更新數的高度c->lChild=T2; if(T2) T2->parent=c;c->rChild=T3; if(T3) T3->parent=c;updateHeight(c);//更新數的高度b->lChild=a; if(T0) a->parent=b;b->rChild=c; if(T2) c->parent=b;updateHeight(c);//更新數的高度return b;//對傳入的節點進行重連操作 } //針對zig,zag旋轉模式,傳入不同的參數調用connect34 template<typename T>BinNodePosi* BST<T>::rotateAt(BinNodePosi* v){BinNodePosi* p=v->parent,g=p->parent;if(g->lChild==p)//p為左孩子,zig旋轉if(p->lChild==v){//v為左孩子,執行zig,zigp->parent=g->parent;//向上連接return connect34(v,p,g,v->lChild,v->rChild,p->rChild,g->rChild);}else{//zig,zag雙旋v->parent=g->parent;return connect34(p,v,g,p->lChild,v->lChild,v->rChild,g->rChild);}else //zag旋轉if(p->rChild==v){//zag,zagp->parent=g->parent;//向上連接return connect34(g,p,v,g->lChild,p->lChild,v->lChild,v->rChild);}else{//zag,zig旋轉v->parent=g->parent;return connect34(g,v,p,g->lChild,v->lChild,v->rChild,p-rChild);}}

insert實現

//將關鍵碼e插入合適的位置,然后調整平衡樹狀態,使其平衡 template<typename T>BinNodePosi* AVL<T>::insert(const T& e){BinNodePosi* x=search(e);if(x) return x;//節點e已存在樹中x=new BinNode<T>(e,_hot);_size++;//_hot查找過程中指向e應該存在的位置,插入過程將導致某一祖先出現不平衡for(BinNodePosi* g=_hot;g;g=g->parent){//從x的位置向上查找檢查每個祖先,直到出現不平衡的祖先if(!AVlBalanced(*g)){//發現失衡的祖先調用3+4重構使之平衡FromParentTo(*g)=rotateAt(tallerChild(tallerChild))//tallerChild查找p,v的位置break; }elseupdateHeight(g);//向上查找順便更新當前g的高度}return x;//返回更新后的結果 }

remove的實現
search查找出要刪除的節點位置,調用remove(),查找失衡的局部子樹, 調用3+4重構使其恢復平衡,remove的實現與insert差不多, 區別只是在于,remove相比insert多調用一次remove函數

注:經過上述操作后, insert,remove復雜度將降低到O(logn)的狀態

總結

以上是生活随笔為你收集整理的AVL树学习总结的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。