1. 程式人生 > >平衡二叉樹AVL樹的實現(c++STL)

平衡二叉樹AVL樹的實現(c++STL)

pre 根節點 code 先序 blog ltr ons void 過程

#include <iostream>
using namespace std;

template<class Type> 
class AVLtree;           

template<class Type>
class TNode
{
    friend  class  AVLtree<Type>;
private:
    Type  data;
    int   balance;    // 平衡因子
    TNode<Type> *leftChild, *rightChild;
public:
    TNode(
const Type &x = Type(),TNode<Type> *left = NULL,TNode<Type> *right = NULL) : data(x) , leftChild(left) , rightChild(right) , balance(0) {} }; template<class Type> class AVLtree { private: TNode<Type> *root; private: void RightBalance(TNode<Type> * &r,bool
&action); void LeftBalance(TNode<Type> *&r,bool &action); void Insert(TNode<Type> * &root,const Type &x,bool &action); void LeftLeft(TNode<Type> * &r); void RightRight(TNode<Type> * &r); void LeftRight(TNode<Type> *&r);
void RightLeft(TNode<Type> *&r); TNode<Type> *Parent(TNode<Type> *p,TNode<Type> *cur); TNode<Type> *FindNodeNext(TNode<Type> *cur); void DeleTNode(TNode<Type> *&cur,TNode<Type> *par); void Remove(TNode<Type> * &r,const Type &x,bool &action); void InOrder(TNode<Type> *p); public: AVLtree(); void Insert(const Type &bt); TNode<Type> *Parent(TNode<Type> *cur); void Remove(const Type &x); void InOrder(); }; // 右平衡處理過程 template<class Type> void AVLtree<Type>::RightBalance(TNode<Type> * &r, bool &action) { TNode<Type> *rightsub = r->rightChild, *leftsub = NULL; switch (rightsub->balance) //判斷右子樹的平衡因子 { case -1: // RR型 r->balance = 0; rightsub->balance = 0; RightRight(r); //RR型處理 action = false; break; case 0: break; case 1: // RL型 leftsub = rightsub->leftChild; switch (leftsub->balance) // 判斷左子樹的平衡因子 { case 0: // RL型 r->balance = 0; rightsub->balance = 0; leftsub->balance = 0; break; case 1: // RLL型 r->balance = 0; leftsub->balance = 0; rightsub->balance = -1; break; case -1: // RLR型 rightsub->balance = 0; leftsub->balance = 0; r->balance= -1; break; } RightLeft(r); // RL折線型轉換處理 action = false; break; } } // 折線型LR處理 template<class Type> void AVLtree<Type>::LeftRight(TNode<Type> *&r) { RightRight(r->leftChild); // 轉換為LL型(一條直線) LeftLeft(r); // LL型處理 } // 折線型RL處理 template<class Type> void AVLtree<Type>::RightLeft(TNode<Type> *&r) { LeftLeft(r->rightChild); // 先轉換為RR型(一條直線) RightRight(r); // RR型處理 } // 1. 把RL轉換為RR 2. LL型處理 template<class Type> void AVLtree<Type>::LeftLeft(TNode<Type> * &r) { TNode<Type> *cur = r; // cur暫存r r = r->leftChild; // 改變r就是改變根 cur->leftChild = r->rightChild;// 改變暫存cur 實現銜接 r->rightChild = cur; // 根的右子樹置為cur } // 1. 把LR轉換為LL 2. RR型處理 template<class Type> void AVLtree<Type>::RightRight(TNode<Type> * &r) { TNode<Type> *cur = r; // cur暫存r r = r->rightChild; // 改變r就是改變根 cur->rightChild = r->leftChild;// 改變暫存cur 實現銜接 r->leftChild = cur; // 根的左子樹置為cur } // 左平衡處理過程 template<class Type> void AVLtree<Type>::LeftBalance(TNode<Type> *&r, bool &action) { TNode<Type> *leftsub = r->leftChild; TNode<Type> *rightsub = leftsub->rightChild; switch (leftsub->balance) { case 1:// LL型 leftsub->balance = 0; r->balance = 0; LeftLeft(r); action = false; break; case 0: action = false; break; case -1:// LR型 switch (rightsub->balance) { case 0:// LR型 r->balance = 0; rightsub->balance = 0; leftsub->balance = 0; break; case -1:// LRR型 r->balance = 0; rightsub->balance = 0; leftsub->balance = 1; break; case 1:// LRL型 rightsub->balance = 0; leftsub->balance = 0; r->balance = -1; break; } LeftRight(r); // LR折線型轉換處理 action = false; break; } } // Insert主函數 template<class Type> void AVLtree<Type>::Insert(TNode<Type> * & root, const Type &x, bool &action) { if (NULL == root) { root = new TNode<Type>(x); return; } else if (x > root->data) { Insert(root->rightChild, x, action); if (action) // 右子樹插入成功 { switch (root->balance) // 需要重置根的平衡因子 { case 1: // 表示左子樹已經存在,現再插入右子樹成功 root->balance = 0; //平衡因子置0 break; case 0: // 表示之前平衡,現再插入右子樹成功 root->balance = -1; //平衡因子置1 break; case -1: // 表示右子樹已經存在,現再插入右子樹成功 RightBalance(root, action); //右平衡 break; } } } else if (x < root->data) { Insert(root->leftChild, x, action); if (action) // 左子樹插入成功 { switch (root->balance) // 需要重置根的平衡因子 { case 1: // 平衡左子樹 LeftBalance(root, action); break; case 0: root->balance = 1; break; case -1: root->balance = 0; action = false; break; } } } else cout << "數據" << x << "重復!" << endl; } // 查找當前節點的父節點 template<class Type> TNode<Type> *AVLtree<Type>::Parent(TNode<Type> *p, TNode<Type> *cur) { if (NULL == p || NULL == cur|| p == cur) return NULL; if (cur == p->leftChild || cur == p->rightChild) return p; if (p->data < cur->data) return Parent(p->rightChild, cur); else return Parent(p->leftChild, cur); } // 查找當前結點的後繼 (先序遍歷的後繼) template<class Type> TNode<Type> *AVLtree<Type>::FindNodeNext(TNode<Type> *cur) { if (NULL == cur) return NULL; TNode<Type> *p = cur->rightChild; while (p->leftChild != NULL) { p = p->leftChild; } return p; } ////////////////////////////////////////////////////////////////////// /////////////////////////////////刪除節點 template<class Type> void AVLtree<Type>::DeleTNode(TNode<Type> *&cur, TNode<Type> *par) { if (NULL == cur) return; // 情況一:刪除的是根節點,那麽它的父節點必定為NULL if (NULL == par) { // cur可能是根結點,並且樹僅僅只有一個根 if (NULL == cur->rightChild && NULL == cur->leftChild) { delete cur; cur = NULL; return; } // 單分支的樹 if (NULL == cur->rightChild) { // 右子樹不存在 TNode<Type> *p = cur; cur = cur->leftChild; delete p; p = NULL; return; } if (NULL == cur->leftChild) { // 左子樹不存在 TNode<Type> *q = cur; cur = cur->rightChild; delete q; q = NULL; return; } } // 情況二:刪除的屬於雙分支的節點 if (cur->leftChild != NULL && cur->rightChild != NULL) { TNode<Type> *p = FindNodeNext(cur); // 鎖定先序遍歷的後繼 // 情況一: if (cur->rightChild == p) { // 說明右子樹僅僅只有一個節點 cur->balance += 1; // 刪除之後平衡因子改變 cur->data = p->data; // 填充數據,意味著改變刪除對象 cur->rightChild = p->rightChild; // 銜接數據 delete p; //刪除節點p p = NULL; return; } // 情況二: // 否則 TNode<Type> *q = Parent(p); // 找到父節點 if (q->balance != 0) // 不等於0,說明刪除後會影響根結點的平衡因子 cur->balance += 1; // 調整根節點的平衡因子 // 否則 q->balance -= 1; // 刪除的是左節點,所以加一 cur->data = p->data; // 填充數據,意味著改變刪除對象 q->leftChild = p->rightChild; // 銜接數據 // 最後才可以動手刪除節點 刪除節點 釋放內存 delete p; p = NULL; return; } // 情況三:單分支(其中包括了葉子節點的情況) if (NULL == cur->leftChild) { TNode<Type> *p = cur; if (cur == par->leftChild) par->leftChild = cur->rightChild; // 銜接數據 else par->rightChild = cur->rightChild; // 銜接數據 delete p; p = NULL; return; } if (NULL == cur->rightChild) { TNode<Type> *q = cur; if (cur == par->leftChild) par->leftChild = cur->leftChild; else par->rightChild = cur->leftChild; delete q; q = NULL; return; } } // 刪除過程的主函數 template<class Type> void AVLtree<Type>::Remove(TNode<Type> * &r, const Type &x, bool &action) { if (NULL == r) return; if (x == r->data) { TNode<Type> *cur = r; // 確定數據的節點信息 TNode<Type> *par = Parent(r);// 確定當前結點的父節點 DeleTNode(r, par); // 刪除當前指針 return; } else if (x > r->data) { // 右邊查找 Remove(r->rightChild, x, action); if (action) { switch (r->balance) { case -1: // 若原來為1,現在刪除了右節點,應該為0 r->balance = 0; break; //若原來為-1,現在又再右枝上刪除了節點, //樹一定不平衡,需要左平衡調整 case 1: LeftBalance(r, action); action = false; break; case 0: // 若原來為0,現在刪除了右節點,應該為-1 r->balance = 1; action = false; break; } } } else if (x < r->data) { Remove(r->leftChild, x, action); if (action) { switch (r->balance) { case -1:// 若原來為1,現在又再左枝上刪除了節點, // 樹一定不平衡,需要右平衡調整 RightBalance(r, action); break; case 1:// 若原來為-1,現在刪除了左節點,應該為0 r->balance = 0; break; case 0:// 若原來為0,現在刪除了左節點,應該為1 r->balance = -1; action = false; break; } } } } template<class Type> AVLtree<Type>::AVLtree(): root(NULL) {} template<class Type> void AVLtree<Type>::Insert(const Type &bt) { bool action = true; Insert(root, bt, action); } template<class Type> TNode<Type> *AVLtree<Type>::Parent(TNode<Type> *cur) { return Parent(root, cur); } template<class Type> void AVLtree<Type>::Remove(const Type &x) { bool action = true; Remove(root, x, action); } template<class Type> void AVLtree<Type>::InOrder(TNode<Type> *p) { if (p != NULL) { InOrder(p->leftChild); cout << p->data << " "; InOrder(p->rightChild); } } template<class Type> void AVLtree<Type>::InOrder() { InOrder(root); cout << endl; }

平衡二叉樹AVL樹的實現(c++STL)