代码改变世界

AVL树

2013-12-03 01:55  凝月流风  阅读(276)  评论(1编辑  收藏  举报

 

之前学习AVL树,便照着书上(《Data structure and program design in C++》)的插入代码敲了一遍加深印象(去掉书上的继承)。

1.AVL树是一种平衡二叉树,通过保持每一个节点的两棵子树的高度差不能超过1来保持树的平衡性。

2.平衡性的保持:当插入新节点时,就可能破坏树的平衡性,针对某一个平衡性被破坏的节点的平衡操作(假设子树已经平衡,递归操作)有4种情况:

                      case1:插入后左子树更高且左子树的左子树比右子树高,此时进行右旋操作

                      case2:插入后左子树更高且左子树的右子树比左子树高,此时进行双旋转操作

                      case3:插入后右子树更高且右子树的右子树比左子树高,此时进行左旋操作

                      case4:插入后右子树更高且右子树的左子树比右子树高,此时进行双旋转操作

  其实只需要分成case1和case2两种情况,case3 和case4只是相反的位置而已

3.代码实现:

   1)插入操作insert()函数调用avl_insert()函数

   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