zoukankan      html  css  js  c++  java
  • 数据结构之AVL树

    1,概述

      AVL树是最早提出的自平衡二叉树,在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树。AVL树中查找、插入和删除在最坏情况下是O(log n),平均情况下针对随机键列表构造的AVL树的高度大约是1.011log2n+0.1(《算法设计与分析,P167》)。因此在平均情况下,查找一棵AVL树需要的比较次数和用折半查找法查找一个有序组几乎是相同的。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。本文介绍了AVL树的设计思想和基本操作。

    2,基本术语

      节点的平衡因子是它的左子树的高度减去它的右子树的高度(有时相反)。带有平衡因子1、0或 -1的节点被认为是平衡的。带有平衡因子 -2或2的节点被认为是不平衡的,并需要重新平衡这个树。平衡因子可以直接存储在每个节点中,或从可能存储在节点中的子树高度计算出来。

    3,基本操作

      AVL树的插入、删除、查找节点操作与普通未平衡的二叉查找树一样。耗费O(log n)时间。与普通二叉查找树的区别是当插入、删除节点时需要保证平衡性。

      有四种种情况可能导致二叉查找树不平衡,分别为:

    有四种种情况可能导致二叉查找树不平衡,分别为:

    (1)LL:插入一个新节点到根节点的左子树(Left)的左子树(Left),导致根节点的平衡因子由1变为2

    (2)RR:插入一个新节点到根节点的右子树(Right)的右子树(Right),导致根节点的平衡因子由-1变为-2

    (3)LR:插入一个新节点到根节点的左子树(Left)的右子树(Right),导致根节点的平衡因子由1变为2

    (4)RL:插入一个新节点到根节点的右子树(Right)的左子树(Left),导致根节点的平衡因子由-1变为-2

      如图所示,对应的处理方法是:(1)右单转(2)左单转(3)左右双转(4)右左双转。如果有若干节点的平衡因子为±2,先找出最靠近新插入叶子的不平衡节点,然后旋转以该节点为根的树。

    4,C++实现

     

    View Code
      1 #include<iostream>
      2 using namespace std;
      3 
      4 #define max(X,Y) ((X > Y) ? X : Y)
      5 
      6 class AVLtree{
      7 public:
      8     AVLtree();
      9     
     10     void insert_node(const int &);        //插入节点
     11     void del_node(const int &);            //删除节点
     12     bool find_node(const int &);        //查找节点
     13     void print();                    //中序遍历,相当于顺序打印
     14     void make_empty();
     15 
     16 private:
     17     struct AVLnode{
     18         int data;
     19         struct AVLnode *left,*right;
     20         int height;            //节点高度
     21     };
     22     struct AVLnode * head;    //根节点
     23     void insert_node(const int &,AVLnode * &);
     24     bool find_node(const int &,AVLnode * &);
     25     void clear(AVLnode * &);
     26 
     27     int height(AVLnode *);        //返回指定节点高度信息
     28 
     29     void single_left(AVLnode * &);                //左单转
     30     void single_right(AVLnode * &);                //右单转
     31     void double_LR(AVLnode * &);                //左右双转
     32     void double_RL(AVLnode * &);                //右左双转
     33     void print(AVLnode * &);
     34     void make_empty(AVLnode * &);
     35 };
     36 
     37 AVLtree::AVLtree()
     38 {
     39     head = NULL;
     40 }
     41 
     42 void AVLtree::insert_node(const int & para)
     43 {
     44     insert_node(para,head);
     45 }
     46 
     47 bool AVLtree::find_node(const int & para)
     48 {
     49     return find_node(para,head);
     50 }
     51 
     52 void AVLtree::print()
     53 {
     54     print(head);
     55 }
     56 
     57 void AVLtree::make_empty()
     58 {
     59     make_empty(head);
     60 }
     61 
     62 void AVLtree::insert_node(const int & para,AVLnode * &root)
     63 {
     64     if(!root)    //空树
     65     {
     66         AVLnode *p = (AVLnode *)malloc(sizeof(AVLnode));
     67         p->data = para;
     68         p->left = NULL;
     69         p->right = NULL;
     70         p->height = 0;
     71 
     72         root = p;    //使父节点指针指向新插入的节点
     73     }
     74     else
     75     {
     76         if(para < root->data)    //插入左子树
     77         {
     78             insert_node(para,root->left);
     79             if(height(root->left) - height(root->right) == 2)//不平衡,两种情况,(1)插入左子树的左子树,(3)插入左子树的右子树
     80             {
     81                 if(para < root->left->data)        //情况(1)
     82                     single_right(root);
     83                 else
     84                     double_LR(root);            //情况(3)
     85             }
     86         }
     87         else if(para > root->data)    //插入右子树
     88         {
     89             insert_node(para,root->right);
     90             if(height(root->left) - height(root->right) == -2)//不平衡,两种情况,(4)插入右子树的左子树,(2)插入右子树的右子树
     91             {
     92                 if(para < root->right->data)    //情况(4)
     93                     double_RL(root);
     94                 else
     95                     single_left(root);            //情况(2)
     96             }
     97         }
     98         else    //该值已存在,不作处理
     99         {}
    100 
    101         //更新节点高度信息
    102         root->height = max(height(root->left),height(root->right)) + 1;
    103     }
    104 }
    105 
    106 bool AVLtree::find_node(const int &para,AVLnode * &root)
    107 {
    108     if(root->data == para)
    109         return true;
    110     else if(root->data > para && (root->left))
    111         find_node(para,root->left);
    112     else if(root->data < para && (root->right))
    113         find_node(para,root->right);
    114     else
    115         return false;
    116 }
    117 
    118 void AVLtree::single_left(AVLnode * &root)
    119 {
    120     AVLnode * temp = root->right;
    121     root->right = temp->left;
    122     temp->left = root;
    123 
    124     //修改节点高度
    125     root->height = max(height(root->left),height(root->right)) + 1;
    126     temp->height = max(height(temp->left),height(temp->right)) + 1;
    127 
    128     root = temp;    //更新根节点指针
    129 }
    130 
    131 void AVLtree::single_right(AVLnode * &root)
    132 {
    133     AVLnode * temp = root->left;
    134     root->left = temp->right;
    135     temp->right = root;
    136 
    137     //修改节点高度
    138     root->height = max(height(root->left),height(root->right)) + 1;
    139     temp->height = max(height(temp->left),height(temp->right)) + 1;
    140 
    141     root = temp;    //更新根节点指针
    142 }
    143 
    144 void AVLtree::double_LR(AVLnode * &root)
    145 {
    146     single_left(root->left);
    147     single_right(root);
    148 }
    149 
    150 void AVLtree::double_RL(AVLnode * &root)
    151 {
    152     single_right(root->right);
    153     single_left(root);
    154 }
    155 
    156 int AVLtree::height(AVLnode * root)
    157 {
    158     if(!root)
    159         return -1;
    160     else
    161         return root->height;
    162 }
    163 
    164 
    165 void AVLtree::print(AVLnode * &root)
    166 {
    167     if(!root)
    168         return;
    169     else
    170     {
    171         print(root->left);
    172         cout<<root->data<<endl;
    173         print(root->right);
    174     }
    175 }
    176 
    177 void AVLtree::make_empty(AVLnode * &root)
    178 {
    179     if(!root)
    180         return;
    181     else
    182     {
    183         make_empty(root->left);
    184         make_empty(root->right);
    185         delete(root);
    186     }
    187     root = NULL;        //缺少这条语句会忘记释放父节点指向本节点的指针,导致重复释放内存,导致错误
    188 }
    189 
    190 int main()
    191 {
    192     AVLtree a;
    193     int array[7] = {5,6,8,3,2,4,7};
    194     for(int i=0;i<7;i++)
    195         a.insert_node(array[i]);
    196     a.print();        //顺序输出数据
    197 
    198     cout<<a.find_node(7)<<endl;
    199     cout<<a.find_node(5)<<endl;
    200     cout<<a.find_node(11)<<endl;
    201     a.make_empty();
    202     return 0;
    203 }

      没有实现删除的算法。

      最近准备整理下几种树的原理和实现,下一篇是红黑树。

     

  • 相关阅读:
    过滤器(Filter)
    DBUtils结果集处理器介绍
    Tomcat配置连接c3p0连接池
    JdbcUtils
    数据库连接池
    JDBC处理事务
    JDBC入门(5)--- 时间类型、大数据
    JDBC入门(4)--- 批处理
    JDBC入门(3)--- PrepareStatement
    JDBC入门(2)--- ResultSet之滚动结果集
  • 原文地址:https://www.cnblogs.com/loopever/p/2537814.html
Copyright © 2011-2022 走看看