AVL樹

 

以前學習AVL樹,便照着書上(《Data structure and program design in C++》)的插入代碼敲了一遍加深印象(去掉書上的繼承)。ios

1.AVL樹是一種平衡二叉樹,經過保持每個節點的兩棵子樹的高度差不能超過1來保持樹的平衡性。函數

2.平衡性的保持:當插入新節點時,就可能破壞樹的平衡性,針對某一個平衡性被破壞的節點的平衡操做(假設子樹已經平衡,遞歸操做)有4種狀況:學習

                      case1:插入後左子樹更高且左子樹的左子樹比右子樹高,此時進行右旋操做測試

                      case2:插入後左子樹更高且左子樹的右子樹比左子樹高,此時進行雙旋轉操做spa

                      case3:插入後右子樹更高且右子樹的右子樹比左子樹高,此時進行左旋操做code

                      case4:插入後右子樹更高且右子樹的左子樹比右子樹高,此時進行雙旋轉操做blog

  其實只須要分紅case1和case2兩種狀況,case3 和case4只是相反的位置而已繼承

3.代碼實現:遞歸

   1)插入操做insert()函數調用avl_insert()函數ci

   2)taller變量的設置很是巧妙,用以判斷子樹是否已經增高

   3)一旦子樹增高則判斷是否須要進行平衡性操做

   4)如下代碼只實現插入操做,中序遍歷用以測試

#include <iostream>
using namespace std; 
enum Balance_factor {
  left_higher,
  equal_height,
  right_higher
};

template<class Entry>
struct Avl_Node {
  Entry data;
  Balance_factor balance;  
  Avl_Node* left;
  Avl_Node* right;
  Avl_Node(Entry& x) {
    data = x;
    left = NULL;
    right = NULL;
    balance = equal_height;
  }
  Avl_Node() {
    left = right = NULL;
    balance = equal_height;
  }
  Balance_factor get_balance() {
   return balance;
  }
  void set_balance(Balance_factor x) {
    balance = x;
  }
};

template<class Entry>
class AVL_Tree {
  public:
    AVL_Tree();
    bool insert(Entry& x);
    bool Remove(Entry& x);
    void Inorder(); //中序遍歷 
    void recursive_inorder(Avl_Node<Entry>*);
  protected:
    Avl_Node<Entry>* root;
    bool avl_insert(Avl_Node<Entry>* &subroot, Entry& newdata, bool &taller);
    void rotate_left(Avl_Node<Entry>* &subroot); //左旋 
    void rotate_right(Avl_Node<Entry>* &subroot);  //右旋 
    void left_balance(Avl_Node<Entry>* &subroot);   //操做左子樹保持平衡 
    void right_balance(Avl_Node<Entry>* &subroot); //操做右子樹保持平衡 
};

//構造函數 
template<class Entry>
AVL_Tree<Entry>::AVL_Tree() {
  root = NULL;
}
//插入數據 
template<class Entry>
bool AVL_Tree<Entry>::insert(Entry& x) {
  bool taller;
  return avl_insert(root, x, taller);
}
//刪除數據 
template<class Entry>
bool AVL_Tree<Entry>::Remove(Entry& x) {
}

template<class Entry>
bool AVL_Tree<Entry>::avl_insert(Avl_Node<Entry>* &subroot, Entry& newdata, bool &taller) {
  bool result = true;
  if (subroot == NULL) {
    subroot = new Avl_Node<Entry>(newdata);
  } else if (newdata < subroot->data) {
        //插入到左子樹 
    result = avl_insert(subroot->left, newdata, taller);
      //插入到子樹完成後判斷子樹高度是否增長,若增長,則可能致使不平衡,進行平衡處理 
    if (taller) {
      switch (subroot->get_balance()) {
        case left_higher :     //若原來左邊更高,在左子樹插入後必然使得左邊繼續增高,致使不平衡,必須進行平衡操做
             left_balance(subroot);
             taller = false;
             break;
        case equal_height :  //若原來兩邊同樣高,那麼插入一個能夠繼續保持差值爲1的平衡性,高度一定增長
             subroot->set_balance(left_higher);
             break;
        case right_higher:   //若原來右子樹更高,那麼增長左子樹高度能夠使樹兩邊高度一致
             taller = false;
             subroot->set_balance(equal_height); 
             break;
      }
    }
  } else {
    result = avl_insert(subroot->right, newdata, taller);
    if (taller) {
      switch (subroot->get_balance()) {
        case left_higher:
             taller = false;
             subroot->set_balance(equal_height);
             break;
        case equal_height :
             subroot->set_balance(right_higher);
             break;
        case right_higher :
             right_balance(subroot);
             taller = false;
            break;
      }
    }
  }
  return result;
}

//左旋操做 
template<class Entry>
void AVL_Tree<Entry>::rotate_left(Avl_Node<Entry>* &subroot) {
  if (subroot == NULL || subroot->right == NULL) {
    cout << "subroot or subroot->right is NULL" << endl;
  } else {
    Avl_Node<Entry>* right_tree = subroot->right;
    subroot->right = right_tree->left;
    right_tree->left = subroot;
    subroot = right_tree; 
  }
}

//右旋操做 
template<class Entry>
void AVL_Tree<Entry>::rotate_right(Avl_Node<Entry>* &subroot) {
  if (subroot == NULL || subroot->left == NULL) {
    cout << "subroot of subroot->left is NULL" << endl;
  } else {
    Avl_Node<Entry>* left_tree = subroot->left;
    subroot->left = left_tree->right;
    left_tree->right = subroot;
    subroot = left_tree;
  }
}

//重點,保持樹的平衡操做,left_balance()函數爲左子樹太高時進行,right_balance()相反
template<class Entry>
void AVL_Tree<Entry>::left_balance(Avl_Node<Entry>* &subroot) {
  Avl_Node<Entry>* left_tree = subroot->left;
  switch (left_tree->get_balance()) {
    case left_higher :   //case1
         subroot->set_balance(equal_height);
         left_tree->set_balance(equal_height);
         rotate_right(subroot);
         break;
    case equal_height :   //error
         cout << "WARNING: program error detected in left_balance" << endl;
    case right_higher :   //case 2 : double rotation
         Avl_Node<Entry>* subtree = left_tree->right;
        switch (subtree->get_balance()) {
          case left_higher :
               subroot->set_balance(right_higher);
               left_tree->set_balance(equal_height);
               break;
          case equal_height :
               subroot->set_balance(equal_height);
               left_tree->set_balance(equal_height);
               break;
          case right_higher :
               subroot->set_balance(equal_height);
               left_tree->set_balance(left_higher);                  
        }
        subtree->set_balance(equal_height);
        rotate_left(left_tree);
        rotate_right(subroot);
        break;             
  }
}

template<class Entry>  // The same as left_balance
void AVL_Tree<Entry>::right_balance(Avl_Node<Entry>* &subroot) {
  Avl_Node<Entry>* right_tree = subroot->right;
  switch (right_tree->get_balance()) {
    case right_higher :  //case3
         subroot->set_balance(equal_height);
         right_tree->set_balance(equal_height);
         rotate_left(subroot);
    case equal_height :  //error
         cout << "WARNING: program error detected in left_balance" << endl;
    case left_higher :  //case4
         Avl_Node<Entry>* subtree = right_tree->left;
         switch (subtree->get_balance()) {
           case left_higher :
                subroot->set_balance(equal_height);
                right_tree->set_balance(right_higher);
                break;
           case equal_height :
                subroot->set_balance(equal_height);
                right_tree->set_balance(equal_height);
                break;
           case right_higher :
                subroot->set_balance(left_higher);
                right_tree->set_balance(equal_height);
                break;
         }
         subtree->set_balance(equal_height);
         rotate_right(right_tree);
         rotate_left(subroot);
         break;
  } 
}
//Test:inorder traversal
template<class Entry>
void AVL_Tree<Entry>::Inorder() {
  recursive_inorder(root);
}
template<class Entry>
void AVL_Tree<Entry>::recursive_inorder(Avl_Node<Entry>* subroot) {
  if (subroot != NULL) {
    recursive_inorder(subroot->left);
    cout << subroot->data << endl;
    recursive_inorder(subroot->right);
  }
}

int main() {
  AVL_Tree<int> avl;
  for (int i = 0; i < 10; i++) {
      int u;
    cin >> u;
    avl.insert(u);
  }
  avl.Inorder();
  return 0;
}

若代碼有誤望能指點,thanks

Next step:SPLY Tree

相關文章
相關標籤/搜索