zoukankan      html  css  js  c++  java
  • 二叉查找树系列六:AVL树

    动态符号表可以用二叉查找树表示,最坏情况下,二叉查找树可完全偏斜,高度为n,其平均和最坏查找时间都是O(n);最好情况下,二叉查找树的结点尽可能靠近根节点,其平均和最坏查找时间都是O(log2n)。因而,为了得到较好的查询效率,最理想的情况是时刻保持树是一棵完全二叉树,然而,为了达到这种要求就会使插入和删除的操作付出很高的代价。对此,人们设计出在高度上相对平衡的二叉查找树,其查找、插入和删除的时间都是O(log2n)。

    AVL树是有Adelson-Velskii和Landis提出的,一种在高度上相对平衡的二叉查找树。由于该树的平衡性,其平均和最坏查找时间都是O(log2n),且插入和删除也只需O(log2n)时间,插入和删除后的树仍是高度上相对平衡的。

    (1)AVL树的定义

    空二叉树是AVL树,如果T是一棵非空二叉查找树,其左子树为TL,右子树为TR,TL的高度为HL,TR的高度为HR,则T是AVL树当且仅当:

    a. TL和TR是AVL树;

    b. |HL-HR|<=1.

    或者说:AVL树是每个结点的左右子树高度最多差1的二叉查找树。

    由斐波那契数可以推出AVL树的高度最多为1.44log(N+2)-1.328,它只比logN多一点。

    (2)AVL树的插入

    当向AVL树中插入新的结点时,需要更新通向根结点路径上那些结点的所有平衡信息,此外,插入可能会破坏AVL树的平衡特性,通常需要在插入后通过修正来保持AVL树的特性,对此常用的方法是旋转。

    假如插入新结点后结点A的两棵子树的高度差为2,那么可以推断插入应是下列四种情况中的一种:

    LL:对A的左儿子的左子树进行一次插入

    LR:对A的左儿子的右子树进行一次插入

    RL:对A的右儿子的左子树进行一次插入

    RR:对A的右儿子的右子树进行一次插入

    上面的情形中LL和RR是对称的,LR和RL是对称的,对于前者,可以通过单旋转恢复AVL树的特性,对于后者可以通过双旋转恢复AVL树的平衡性。

    a. 单旋转

    LL情形下:

    如下图所示:结点k2不满足AVL平衡特性,左子树比右子树的高度高2。通过调整之后,k1成了树根,二叉查找树的性质又使k2成为了k1的右儿子,Y成为了k2的左儿子,二叉查找树的性质没有被破坏,且AVL的特性也恢复了。

    对应的,RR情形的单旋转如下:其中k1成为k2的左儿子,Y成为k1的右儿子

    b. 双旋转

    LR情形:如果插入是在结点的左儿子的右子树中,那么通过单旋转并不能恢复AVL树的平衡特性,如下图:

    此时就需要双旋转,如下图所示,调整的过程中首先找出不平衡点k3,顺着k3依次找出3个点:k3,k1,k2,k2是最后一个点,它将成为旋转后的新的根结点,并根据二叉查找树的性质让k1,k3分别成为k2的左右儿子,B和C分别成为k1和k3的右儿子和左儿子:

    对应的,对于RL情形,旋转如下:

    (3)AVL树插入C++实现

     设计两个类AVLNode和AVLTree,其中AVLTree为AVLNode的友元:

      1 /***********AVLNode.h***********/
      2 #ifndef AVLNODE_H
      3 #define AVLNODE_H
      4 
      5 template<class T> class AVLTree;
      6 template<class T>
      7 class AVLNode
      8 {
      9 friend class AVLTree<T>;
     10 public:
     11     AVLNode()
     12     {
     13         data = 0;
     14         left = NULL;
     15         right = NULL;
     16         height = 0;
     17     }
     18     AVLNode(T val)
     19     {
     20         data = val;
     21         left = NULL;
     22         right = NULL;
     23         height = 0;
     24     }
     25 
     26 public:
     27     T data;
     28     AVLNode* left;
     29     AVLNode* right;
     30     int height;
     31 };
     32 
     33 #endif
     34 
     35 /************AVLTree.h**************/
     36 #ifndef AVLTREE_H
     37 #define AVLTREE_H
     38 
     39 #include "AVLNode.h"
     40 
     41 template<class T>
     42 class AVLTree
     43 {
     44 public:
     45     AVLTree();
     46     AVLNode<T>* Insert(const T data, AVLNode<T>* node);
     47     void LevelOrder(AVLNode<T>* root);
     48 private:
     49     AVLNode<T>* root;
     50 };
     51 
     52 #endif
     53 
     54 /************AVLTree.CPP**************/
     55 #include "AVLNode.h"
     56 #include "AVLTree.h"
     57 #include<queue>
     58 #include<iostream>
     59 using namespace std;
     60 
     61 template<class T>
     62 AVLTree<T>::AVLTree()
     63 {
     64     root = NULL;
     65 }
     66 
     67 template<class T>
     68 int Height(AVLNode<T>* node)
     69 {
     70     if(node != NULL)
     71         return node->height;
     72     return -1;
     73 }
     74 
     75 template<class T>
     76 AVLNode<T>* SingleRotateWithLeft(AVLNode<T>* node)
     77 {
     78     if(node != NULL)
     79     {
     80         AVLNode<T>* k;
     81         k = node->left;
     82         node->left = k->right;
     83         k->right = node;
     84 
     85         node->height = max(Height(node->left),Height(node->right)) + 1;
     86         k->height = max(Height(k->left),Height(k->right)) + 1;
     87 
     88         return k;
     89     }
     90     return NULL;
     91 }
     92 
     93 template<class T>
     94 AVLNode<T>* SingleRotateWithRight(AVLNode<T>* node)
     95 {
     96     if(node != NULL)
     97     {
     98         AVLNode<T>* k;
     99         k = node->right;
    100         node->right = k->left;
    101         k->left = node;
    102 
    103         node->height = max(Height(node->left),Height(node->right)) + 1;
    104         k->height = max(Height(k->left),Height(k->right)) + 1;    
    105 
    106         return k;
    107     }
    108     return NULL;
    109 }
    110 
    111 template<class T>
    112 AVLNode<T>* DoubleRotateWithLeft(AVLNode<T>* node)
    113 {
    114     node->left = SingleRotateWithRight(node->left);
    115     return SingleRotateWithLeft(node);
    116 }
    117 
    118 template<class T>
    119 AVLNode<T>* DoubleRotateWithRight(AVLNode<T>* node)
    120 {
    121     node->right = SingleRotateWithLeft(node->right);
    122     return SingleRotateWithRight(node);
    123 }
    124 
    125 template<class T>
    126 void AVLTree<T>::LevelOrder(AVLNode<T>* root)
    127 {
    128     if(root != NULL)
    129     {    
    130         queue<AVLNode<T>*> q;
    131         AVLNode<T>* curr = root;
    132         AVLNode<T>* temp = root;
    133         while(curr)
    134         {
    135             cout<<curr->data<<"("<<curr->height<<")"<<endl;
    136             if(curr->left)
    137                 q.push(curr->left);
    138             if(curr->right)
    139                 q.push(curr->right);
    140             if(!q.empty())
    141             {
    142                 curr = q.front();
    143                 q.pop();
    144             }
    145             else
    146                 curr = NULL;
    147         }
    148     }
    149 }
    150 
    151 template<class T>
    152 AVLNode<T>* AVLTree<T>::Insert(const T data, AVLNode<T>* root)
    153 {
    154     if(root == NULL)
    155         return root = new AVLNode<T>(data);
    156     else
    157     {
    158         AVLNode<T>* node = root;
    159         if(node->data > data)
    160         {
    161             node->left = Insert(data,node->left);
    162             if(Height(node->left) - Height(node->right) == 2)
    163             {
    164                 if(data < node->left->data)
    165                     node = SingleRotateWithLeft(node);
    166                 else
    167                     node = DoubleRotateWithLeft(node);
    168             }            
    169         }
    170         else if(node->data < data)
    171         {
    172             node->right = Insert(data,node->right);
    173             if(Height(node->right) - Height(node->left) == 2)
    174             {
    175                 if(data > node->right->data)
    176                     node = SingleRotateWithRight(node);
    177                 else
    178                     node = DoubleRotateWithRight(node);
    179             }
    180         }
    181         node->height = max(Height(node->left),Height(node->right))+1;
    182         return node;
    183     }
    184     
    185 }
    186 
    187 // AVL.cpp : 定义控制台应用程序的入口点。
    188 //
    189 
    190 #include "stdafx.h"
    191 #include "AVLNode.h"
    192 #include "AVLTree.h"
    193 #include "AVLTree.cpp"
    194 
    195 #include <iostream>
    196 
    197 using namespace std;
    198 
    199 
    200 int _tmain(int argc, _TCHAR* argv[])
    201 {
    202     AVLTree<int> avl;
    203     AVLNode<int>* root = avl.Insert(3,NULL);
    204     root = avl.Insert(2,root);
    205     root = avl.Insert(1,root);
    206 
    207     avl.LevelOrder(root);
    208 
    209      system("pause");
    210     return 0;
    211 }
    View Code
  • 相关阅读:
    自定义组件要加@click方法
    绑定样式
    647. Palindromic Substrings
    215. Kth Largest Element in an Array
    448. Find All Numbers Disappeared in an Array
    287. Find the Duplicate Number
    283. Move Zeroes
    234. Palindrome Linked List
    202. Happy Number
    217. Contains Duplicate
  • 原文地址:https://www.cnblogs.com/sophia-yun/p/3167381.html
Copyright © 2011-2022 走看看