zoukankan      html  css  js  c++  java
  • AVL树

    之前学习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

  • 相关阅读:
    第一个MIPS汇编
    选你所爱,爱你所选
    海明码(汉明码)的工作机制
    第一个x86汇编程序
    机器学习 coursera【week1-3】
    描述符应用与类的装饰器
    多态,封装,反射,类内置attr属性,os操作复习
    面向对象操作
    类属性的增删改查,类属性和实例属性
    os常用模块,json,pickle,shelve模块,正则表达式(实现运算符分离),logging模块,配置模块,路径叠加,哈希算法
  • 原文地址:https://www.cnblogs.com/Patrickcxt/p/3455037.html
Copyright © 2011-2022 走看看