平衡搜索树—AVLTree

  AVL是平衡搜索二叉树,它的主要特点在于:(1)左子树和右子树的高度差绝对值<1,(2)树中的每个子树都是AVL树,(3)每个节点都有一个平衡因子(-1、0、1),平衡因子的大小等于右子树的高度减左子树的高度

下面就是一个AVL树:

其中,这个树满足左子树和右子树的高度差绝对值小于1,每个节点的平衡因子都满足条件。

下面是AVLTree中节点的结构:

template <class K, class V>
struct AVLTreeNode
{
     K _key;
     V _value;
     int _bf;     //节点的平衡因子
     AVLTreeNode<K, V>* _parent;     //指向节点的父节点
     AVLTreeNode<K, V>* _left;       //指向节点的左孩子
     AVLTreeNode<K, V>* _right;      //指向节点的右孩子
     
     AVLTreeNode(const K& key = K(), const V& value = V())    //构造节点
          :_key(key)
          , _value(value)
          , _parent(NULL)
          , _left(NULL)
          , _right(NULL)
          , _bf(0)
     { }
};

      下面讨论一下AVLTree中插入节点的情况:

当插入一个节点时,如果这个节点的父节点的平衡因子不满足AVLTree的特点,这时就需要对AVLTree进行调整,直到满足AVLTree的条件。


(1)左单旋

(2)右单旋

(3)左右双旋

(4)右左双旋

       针对上面的情况,下面是具体的程序实现:

#pragma once
#include <assert.h>
#include <math.h>
//实现平衡搜索二叉树
//构造AVL树的节点(使用三叉链表)

template <class K, class V>
struct AVLTreeNode
{
     K _key;
     V _value;
     int _bf;
     AVLTreeNode<K, V>* _parent;
     AVLTreeNode<K, V>* _left;
     AVLTreeNode<K, V>* _right;
     
     AVLTreeNode(const K& key = K(), const V& value = V())    //构造节点
          :_key(key)
          , _value(value)
          , _parent(NULL)
          , _left(NULL)
          , _right(NULL)
          , _bf(0)
     { }
};

template <class K, class V>
class AVLTree
{
     typedef AVLTreeNode<K, V> Node;
public:
     AVLTree()     //初始化根节点
          :_root(NULL)
     { }
     
     bool Insert(const K& key, const V& value)    //插入
     {
          //根节点判空
          if (_root == NULL)
          {
               _root = new Node(key, value);
               return true;
          }
          //将数据先插入到树中
          Node* cur = _root;
          Node* parent = NULL;
          Node* tmp = new Node(key, value);
          while (cur)
          {
               if (cur->_key < key)
               {
                    parent = cur;
                    cur = cur->_right;
               }
               else if (cur->_key > key)
               {
                    parent = cur;
                    cur = cur->_left;
               }
               else
               {
                    return false;
               }
          }
          if (parent->_key > key)
          {
               parent->_left = tmp;
               tmp->_parent = parent;
          }
          if (parent->_key < key)
          {
               parent->_right = tmp;
               tmp->_parent = parent;
          }
          
          //对树进行调整
          cur = tmp;
          parent = cur->_parent;
          bool isRotate = false;
          while (parent)
          {
               if (parent->_left == cur)     //插入左节点,父亲节点的平衡因子-1
               {
                    parent->_bf--;
               }
               if (parent->_right == cur)   //插入右节点,父亲节点的平衡因子+1
               {
                    parent->_bf++;
               }
               if (parent->_bf == 0)     
                //调整过程中,若碰到平衡因子为0的节点,就不用在继续调整
               {
                    break;
               }
               else if (parent->_bf == -1 || parent->_bf == 1)   //更新平衡因子
               {
                    cur = parent;
                    parent = cur->_parent;
               }
               else
               {
                    if (parent->_bf == 2)
                    {
                         if (cur->_bf == 1)      //左单旋
                         {
                              _RotateL(parent);
                         }
                         else       //右左单旋
                         {
                              _RotateRL(parent);
                         }
                    }
                    else           //=-2
                    {
                         if (cur->_bf == -1)      //右单旋
                         {
                              _RotateR(parent);
                         }
                         else                     //左右单旋
                         {
                              _RotateLR(parent);
                         }  
                    }
                    isRotate = true;
               }
               break;
          }
          
          if (isRotate)
          {
               if (parent->_parent == NULL)
               {
                    _root = parent;
                    return true;
               }
          }
          return true;
     }
     
     void InOrder()     //后序遍历
     {
          _InOrder(_root);
          cout << endl;
     }
     
     bool IsBalance()
     {
          if (_root == NULL)
          {
               cout << "root is null!" << endl;
               return false;
          }
          return _IsBalance(_root);
     }
     
     int Heigth()
     {
          int heigthTree = 0;
          Node* cur = _root;
          while (cur)
          {
               if (cur != NULL)
               {
                    heigthTree++;
               }
               cur = cur->_left;
          }
          return _Heigth(_root, heigthTree, 0);
     }
    
protected:
     int _Heigth(Node* root, int heigthTree, int countNum)
     { 
          if (root == NULL)
          {
               if (countNum > heigthTree)
               {
                    heigthTree = countNum;
               }
               return heigthTree;
          }
          _Heigth(root->_left, heigthTree, countNum++);
          _Heigth(root->_right, heigthTree, countNum++);
     }
     
     bool _IsBalance(Node* root)
     {
          int bf = root->_right->_bf - root->_right->_bf;
          if (bf == 0 || bf == 1 || bf == -1)
          {
               return true;
          }
          else
          {
               return false;
          }
          _IsBalance(root->_left);
          _IsBalance(root->_right);
     }
    
     void _RotateL(Node*& parent)     //左单旋
     {
          Node* SubR = parent->_right;    //新建两个节点指针
          Node* SubRL = SubR->_left;
          parent->_right = SubRL;        //进行调整
          if (SubRL)
          {
               SubRL->_parent = parent;
          }
          SubR->_left = parent;
          SubR->_parent = parent->_parent;
          parent->_parent = SubR;
          parent->_bf = SubR->_bf = 0;    //更改引用计数
          parent = SubR;
     }
     
     void _RotateR(Node*& parent)     //右单旋
     {
          Node* SubL = parent->_left;   //新建两个节点指针
          Node* SubLR = SubL->_right;
          parent->_left = SubLR;    //进行调整
          if (SubLR)
          {
               SubLR->_parent = parent;
          }
          SubL->_right = parent;
          SubL->_parent = parent->_parent;
          parent->_parent = SubL;
          parent->_bf = SubL->_bf = 0;
          parent = SubL;
     }
     
     void _RotateRL(Node*& parent)     //右左单旋
     {
          Node* pNode = parent;
          Node* subRNode = parent->_right;
          Node* subRLNode = subRNode->_left;
          int bf = subRLNode->_bf;
          _RotateR(parent->_right);
          _RotateL(parent);
          if (bf == -1)
          {
               subRNode->_bf = 0;
               pNode->_bf = -1;
          }
          else if (bf == 1)
          {
               subRNode->_bf = 1;
               pNode->_bf = 0;
          }
          else
          {
               subRNode->_bf = 0;
               pNode->_bf = 0;
          }
          subRNode->_bf = 0;
     }
     
     void _RotateLR(Node*& parent)     //左右单旋
     {
          Node* pNode = parent;
          Node* subLNode = parent->_left;
          Node* subLRNode = subLNode->_right;
          int bf = subLRNode->_bf;
          _RotateL(parent->_left);
          _RotateR(parent);
          if (bf == -1)
          {
               subLNode->_bf = 0;
               pNode->_bf = 1;
          }
          else if (bf == 1)
          {
               subLNode->_bf = -1;
               pNode->_bf = 0;
          }
          else
          {
               subLNode->_bf = 0;
               pNode->_bf = 0;
          }
          subLNode->_bf = 0;
     }
     
     void _InOrder(Node* root)
     {
          if (root == NULL)
          {
               return;
          }
          _InOrder(root->_left);
          cout << root->_key << " ";
          _InOrder(root->_right);
     }
     
protected:
     Node* _root;
};

void Test()
{
     AVLTree<int, int> ht;
     /*ht.Insert(16, 1);
     ht.Insert(3, 1);
     ht.Insert(7, 1);
     ht.Insert(11, 1);
     ht.Insert(9, 1);
     ht.Insert(26, 1);
     ht.Insert(18, 1);
     ht.Insert(14, 1);
     ht.Insert(15, 1);*/
     
     ht.Insert(4, 1);
     ht.Insert(2, 1);
     ht.Insert(6, 1);
     ht.Insert(1, 1);
     ht.Insert(3, 1);
     ht.Insert(5, 1);
     ht.Insert(15, 1);
     ht.Insert(7, 1);
     ht.Insert(16, 1);
     ht.Insert(14, 1);
     
     ht.InOrder();
     cout<<ht.IsBalance()<<endl;
     cout << ht.Heigth() << endl;
}
时间: 2024-11-07 04:30:59

平衡搜索树—AVLTree的相关文章

平衡搜索树(三) B-Tree

B树的简介 B 树是为了磁盘或其它存储设备而设计的一种多叉平衡查找树.与红黑树很相似,但在降低磁盘I/0操作方面要更好一些(树的深度较低).许多数据库系统都一般使用B树或者B树的各种变形结构.B树与红黑树最大的不同在于,B树的结点可以有许多子女,从几个到几千个.那为什么又说B树与红黑树很相似呢?因为与红黑树一样,一棵含n个结点的B树的高度也为O(lgn),但可能比一棵红黑树的高度小许多,应为它的分支因子比较大.所以,B树可以在O(logn)时间内,实现各种如插入(insert),删除(delet

高度平衡的二叉搜索树—AVLTree

AVL树 AVL树又称为高度平衡的二叉搜索树,是1962年有俄罗斯的数学家G.M.Adel'son-Vel'skii和E.M.Landis提出来的.它能保持二叉树的高度平衡,尽量降低二叉树的高度,减少树的平均搜索长度. AVL树的性质 左子树和右子树的高度之差的绝对值不超过1 树中的每个左子树和右子树都是AVL树 每个节点都有一个平衡因子(balance factor--bf),任一节点的平衡因子是-1,0,1.(每个节点的平衡因子等于右子树的高度减去左子树的高度 ) AVL树的效率 一棵AVL

平衡搜索树

------------------------------------------------------读<算法>后感 一直以来,对于红黑树都没有很好的理解,指导看了<算法>和上了coursera上的公开课,终于算是有了较好的理解,现写下来和大家分享 前言:2-3查找树 虽然二叉搜索树已经很好的解决大多数搜索问题,但是在最坏的情况下的性能还是很差 (~N),为了保证查找的树的平衡.我们引入了3-结点(相较于二叉查找树中的2-结点),并据此构造出2-3查找树.其性质如下: All

平衡搜索树(二) Rb 红黑树

Rb树简介 红黑树是一棵二叉搜索树,它在每个节点上增加了一个存储位来表示节点的颜色,可以是Red或Black.通过对任何一条从根到叶子简单 路径上的颜色来约束,红黑树保证最长路径不超过最短路径的两倍,因而近似于平衡.(性质3.性质4保证了红黑树最长的路径不超过最短路径的两倍) 如图所示: 红黑树是满足下面红黑性质的二叉搜索树 1. 每个节点,不是红色就是黑色的 2. 根节点是黑色的 3. 如果一个节点是红色的,则它的两个子节点是黑色的 4. 对每个节点,从该节点到其所有后代叶节点的简单路径上,均

平衡搜索树--红黑树 RBTree

红黑树是一棵二叉搜索树,它在每个节点上增加了一个存储位来表示节点的颜色,可以是Red或Black. 通过对任何一条从根到叶子节点简单路径上的颜色来约束树的高度,红黑树保证最长路径不超过最短路径的两倍,因而近似于平衡. 红黑树是满足下面红黑性质的二叉搜索树: 1. 每个节点,不是红色就是黑色的 2. 根节点是黑色的 3. 如果一个节点是红色的,则它的两个子节点是黑色的(不存在连续的红色节点) 4. 对每个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点. 思考:为什么满足上面

【算法导论】 第十课 平衡搜索树

树的结构,如果不能保持平衡,那么其搜索性能会大大打折扣,而本节课介绍了几种经典的平衡树,如AVL,2-3-4tree,红黑树等等,然后着重讲了红黑树,接下来就红黑树的基本性质,作一些简短的总结. 首先,红黑树除了具有BST的基本性质外,还额外拥有以下的五大基本性质: 1)每个结点有一个色域,一个结点要么为黑结点,要么为红结点 2)根节点为黑结点 3)每个叶子结点都为黑结点(无键值) 4)每个红结点的父亲都为黑结点,即不可能出现两个红色结点相连的情况 5)从根节点到任意叶节点的路径中的黑色结点数目

平衡二叉搜索树

AVL树又称高度平衡的二叉搜索树,是1962年俄罗斯的数学家提出来的.它能保持二叉树的高度平衡,尽量降低二叉树的高度,减少树的平均搜索长度. AVL的性质: (1)左子树和右子树的高度之差的绝对值不超过1. (2)树中的每个左子树和右子树都是AVL树. (3)每个节点都有一个平衡因子,任一节点的平衡因子是-1,0,1(每个节点的平衡因子等于右子树的高度减去左子树的高度). 代码实现如下: #include<iostream> using namespace std; template<c

AVL平衡树 - 二叉搜索树的推广

AVL树的介绍 实现 1 旋转 LL左左 RR右右 LR左右 RL右左 2 插入 3 删除 性能 完整代码和参考资料 1. AVL树的介绍 AVL树是根据它的发明者G.M. Adelson-Velsky和E.M. Landis命名的. 它是最先发明的自平衡二叉查找树,也被称为高度平衡树.相比于"二叉查找树",它的特点是:AVL树中任何节点的两个子树的高度最大差别为1. 如上图(左):非AVL树,如对节点9,左子树高度为0,右子树高度为2 如上图(由):AVL树,对任意节点的两个子树高度

二叉搜索树—RBTree(红黑树)

  红黑树又称二叉搜索树,它主要是通过红和黑两种颜色(red.black)来标识节点.通过对任何一条从根节点到叶子节点路径上的节点颜色进行约束,红黑树保证最长路径不超过最短路径的两倍,所以说:红黑树是近似于平衡的. ■下面是红黑树的主要特点: (1)红黑树的根节点是黑色的. (2)红黑树中若一个节点是红色的,则它的两个子节点必须是黑色的. (3)红黑树中从该节点到后代叶节点的路径上,黑色节点数目是相同的.        ◆红黑树的应用: C++库.linux内核.java库等        ◆红