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()接口進行重寫
注:空樹的高度取-1, 單節點子樹高度取0
例: 如圖所示節點的平衡因子(皆為左子樹高度-右子樹高度)
節點的插入以及刪除都將影響節點的平衡度
重平衡
在插入x后, AVL失衡, 可沿x出發向上尋找首次出現失衡的節點, 將其確定為祖父節點(g(x)),然后根據g(x),找到g(x)的兒子節點, 孫子節點, 將其設置為p,v, 由于原樹為平衡的,所以在整個向上查找g的過程只需O(logn)的時間 ; 針對g, p, v三個節點的位置進行zig(順時針旋轉節點,使后代上升為父節點), zag(逆時針)旋轉,用于重平衡
單旋: 只執行zig/zag旋轉,且執行一次
雙旋: 旋轉過程中即包含zig又包含zag
插入過程中的重平衡
當節點x插入后, 可能導致二叉樹結構一系列節點發生不平衡現象(也就是重心偏向一邊), 但是經過局部旋轉后將可能導致一系列的恢復平衡
刪除過程中的重平衡
當節點x刪除后, 只會導致局部的節點發生不平衡現象, 當對局部的不平衡進行zig/zag調整時, 局部子樹的高度將有可能降低,又有可能導致上一層的祖先發生不平衡,因此需要不斷向上遍歷,發現一個失衡的祖先則將其旋轉至平衡狀態,直到更新到沒有出現不平衡現象
統一重平衡算法
在刪除與插入的過程中都涉及到zig,zag旋轉,于是可將插入,刪除操作統一,為避免通過zig,zag旋轉出現的繁瑣,于是提出了3+4重構的方式
3+4重構: 直接傳入g,p,v三個節點以及這三個節點對應的左右子樹,對其進行全部重新連接,由此可覆蓋所有的旋轉操作
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)的狀態
總結
- 上一篇: mft按钮设计_哈汽机组660MW超临界
- 下一篇: 目录树 删除 数据结构_数据结构:B树和