C++类实现AVL树

二叉查找树是个好东西,他让查找,插入,删除,这些常用操作变得高效,但是,他是存在问题的,那就是,在坏的输入序列下,树会退化成链表,这就很尴尬了,于是为了避免这种情况的发生,我们需要一种数据结构,可以自动对树进行调整,我们希望树尽量平衡,于是我们使用平衡因子作为指标,保持任意节点左右子树深度差不超过1,这就可以让树的深度很理想了(接近log2N),如何对树进行调整呢?我们通过旋转来完成他。

#include <iostream>
#include <queue>

class AVLT{//小于向左,大于等于向右,元素类型需支持 <
private:
    typedef int Element;
    struct AVLTNode{
        Element data;
        AVLTNode *left;
        AVLTNode *right;
        int Deepth;
        AVLTNode();
        ~AVLTNode();
        bool isLeaf()const;
        void nodeInsect(const Element &e);
        void nodeDelete(const Element &e);
        const AVLTNode *Find(const Element &e)const;
        const Element& Min()const;
        const Element& Max()const;
        void nodeTraverseFrist(std::ostream& os = std::cout)const;
        void nodeTraverseMid(std::ostream& os = std::cout)const;
        void nodeTraverseLast(std::ostream& os = std::cout)const;
        void nodeTraverselevel(std::ostream& os = std::cout)const;
        const AVLTNode & operator =(const AVLTNode &T);
        void swapdata(AVLTNode&a, AVLTNode&b)const;
        void SingleLeftRotation();
        void SingleRightRotation();
        void DoubleRightLeftRotation();
        void DoubleLeftRightRotation();
        inline void renewDeepth();
        inline int max(int a, int b)const;
    };
    AVLTNode *node;
    int number_of_Node;
public:
    AVLT();
    AVLT(Element *arr, int size);
    AVLT(const AVLT &T);
    ~AVLT();
    bool empty()const;
    const Element& Max()const;
    const Element& Min()const;
    const AVLT &operator = (const AVLT&T);
    void TraverseFrist(std::ostream& os = std::cout)const;
    void TraverseLast(std::ostream& os = std::cout)const;
    void TraverseMid(std::ostream& os = std::cout)const;
    void Traverselevel(std::ostream& os = std::cout)const;
    void Insect(const AVLT::Element &e);
    bool Delete(const AVLT::Element &e);
    int Deepth();
    int Node();
    const AVLTNode* find(const Element &e)const;
};

AVLT::AVLTNode::AVLTNode():left(NULL), right(NULL), Deepth(0){}
AVLT::AVLTNode::~AVLTNode(){
    delete left;
    delete right;
}
bool AVLT::AVLTNode::isLeaf()const{
    return left == NULL&&right == NULL;
}
void AVLT::AVLTNode::nodeInsect(const Element &e){
    if (Deepth == 0){
        Deepth = 1;
        data = e;
        return;
    }
    if (e<data){
        if (left == NULL){
            left = new AVLTNode;
        }
        left->nodeInsect(e);
        if (right){
            if (left->Deepth - right->Deepth > 1){
                if (e<left->data){
                    this->SingleRightRotation();
                }
                else{
                    this->DoubleLeftRightRotation();
                }
            }
        }
        else{
            if (left->Deepth > 1){
                if (e<left->data){
                    this->SingleRightRotation();
                }
                else{
                    this->DoubleLeftRightRotation();
                }
            }
        }
        renewDeepth();
    }
    else{
        if (right == NULL){
            right = new AVLTNode;
        }
        right->nodeInsect(e);
        if (left){
            if (right->Deepth - left->Deepth > 1){
                if (e<right->data){
                    this->DoubleRightLeftRotation();
                }
                else{
                    this->SingleLeftRotation();
                }
            }
        }
        else{
            if (right->Deepth > 1){
                if (e<right->data){
                    this->DoubleRightLeftRotation();
                }
                else{
                    this->SingleLeftRotation();
                }
            }
        }
        renewDeepth();
    }
    return;
}
void AVLT::AVLTNode::nodeDelete(const Element &e){
    if (e<data){
        if (left){
            if (left->isLeaf()){
                delete left;
                left = NULL;
            }
            else
                left->nodeDelete(e);
            {
                int rd = right ? right->Deepth : 0;
                int ld = left ? left->Deepth : 0;
                if (rd - ld >1){
                    if (right->left){
                        DoubleRightLeftRotation();
                    }
                    else{
                        SingleLeftRotation();
                    }
                }
                renewDeepth();
            }
        }
        return;
    }
    else{
        if (data<e){
            if (right){
                if (right->isLeaf()){
                    delete right;
                    right = NULL;
                }
                else
                    right->nodeDelete(e);
                {
                    int rd = right ? right->Deepth : 0;
                    int ld = left ? left->Deepth : 0;
                    if (ld - rd >1){
                        if (left->right){
                            DoubleLeftRightRotation();
                        }
                        else{
                            SingleRightRotation();
                        }
                    }
                    renewDeepth();
                }
                return;
            }
        }
        else{
            if (left == NULL&&right){
                AVLTNode *t = right;
                if (left)
                    delete left;
                left = t->left;
                right = t->right;
                data = t->data;
                Deepth -= 1;
                t->left = t->right = NULL;
                delete t;
                return;
            }
            else{
                if (right == NULL && left){
                    AVLTNode *t = left;
                    if (right)
                        delete right;
                    right = t->right;
                    left = t->left;
                    data = t->data;
                    Deepth -= 1;
                    t->left = t->right = NULL;
                    delete t;
                    return;
                }
                else{

                    AVLTNode *t = left;
                    while (t->right)
                        t = t->right;
                    Element te = t->data;
                    if (left->isLeaf()){
                        delete left;
                        left = NULL;
                    }
                    else
                        left->nodeDelete(te);
                    data = te;
                    return;
                }
            }
        }
    }
    std::cout << "return false" << std::endl;
    return;
}
AVLT::AVLTNode const *AVLT::AVLTNode::Find(const Element &e)const{
    if (e<data){
        if (left)
            return left->Find(e);
    }
    else{
        if (data<e){
            if (right)
                return right->Find(e);
        }
        else{
            return this;
        }
    }
    return NULL;
}
const AVLT::Element& AVLT::AVLTNode::Max()const{
    const AVLTNode *t = this;
    while (t->right)
        t = t->right;
    return t->data;
}
const AVLT::Element& AVLT::AVLTNode::Min()const{
    const AVLTNode *t = this;
    while (t->left)
        t = t->left;
    return t->data;
}
void AVLT::AVLTNode::nodeTraverseFrist(std::ostream& os)const{
    os << this->data << ‘ ‘;
    if (left)
        this->left->nodeTraverseFrist();
    if (right)
        this->right->nodeTraverseFrist();
}
void AVLT::AVLTNode::nodeTraverseMid(std::ostream& os )const{
    if (left)
        this->left->nodeTraverseMid();
    os << this->data << ‘ ‘;
    if (right)
        this->right->nodeTraverseMid();
}
void AVLT::AVLTNode::nodeTraverseLast(std::ostream& os )const{
    if (left)
        this->left->nodeTraverseLast();
    if (right)
        this->right->nodeTraverseLast();
    os << this->data << ‘ ‘;
}
void AVLT::AVLTNode::nodeTraverselevel(std::ostream& os)const{
    std::queue<AVLTNode> q;
    q.push(*this);
    while (!q.empty()){
        AVLTNode p = q.front();
        q.pop();
        os << p.data << ‘ ‘;
        if (p.left){
            q.push(*(p.left));
        }
        if (p.right){
            q.push(*(p.right));
        }
    }
}
const AVLT::AVLTNode & AVLT::AVLTNode::operator =(const AVLTNode &T){
    if (Deepth == 0){
        Deepth = 1;
        data = T.data;
    }
    if (T.left){
        if (left == NULL){
            left = new AVLTNode;
        }
        *left = *T.left;
        if (right){
            Deepth = max(left->Deepth, right->Deepth) + 1;
        }
        else{
            Deepth = left->Deepth + 1;
        }
    }
    if (T.right){
        if (right == NULL){
            right = new AVLTNode;
        }
        *right = *T.right;
        if (left){
            Deepth = max(left->Deepth, right->Deepth) + 1;
        }
        else{
            Deepth = right->Deepth + 1;
        }
    }
    return *this;
}
void AVLT::AVLTNode::swapdata(AVLTNode&a, AVLTNode&b)const{
    Element t;
    t = a.data;
    a.data = b.data;
    b.data = t;
}
void AVLT::AVLTNode::SingleLeftRotation(){
    AVLTNode *a = right;
    right = a->right;
    a->right = a->left;
    a->left = left;
    left = a;
    if (a->right&&a->left){
        a->Deepth = max(a->left->Deepth, a->right->Deepth) + 1;
    }
    else
        if (a->left){
            a->Deepth = a->left->Deepth + 1;
        }
        else{
            a->Deepth = 1;
        }
        swapdata(*this, *a);
}
void AVLT::AVLTNode::SingleRightRotation(){
    AVLTNode *a = left;
    left = a->left;
    a->left = a->right;
    a->right = right;
    right = a;
    if (a->right&&a->left){
        a->Deepth = max(a->left->Deepth, a->right->Deepth) + 1;
    }
    else
        if (a->left){
            a->Deepth = a->left->Deepth + 1;
        }
        else{
            a->Deepth = 1;
        }
        swapdata(*this, *a);
}
void AVLT::AVLTNode::DoubleLeftRightRotation(){
    this->left->SingleLeftRotation();
    this->SingleRightRotation();
}
void AVLT::AVLTNode::DoubleRightLeftRotation(){
    this->right->SingleRightRotation();
    this->SingleLeftRotation();
}
inline void AVLT::AVLTNode::renewDeepth(){
    Deepth = max(left ? left->Deepth : 0, right ? right->Deepth : 0) + 1;
}
inline int AVLT::AVLTNode::max(int a, int b)const{
    return a > b ? a : b;
}

AVLT::AVLT():node(NULL), number_of_Node(0){
}
AVLT::AVLT(Element *arr, int size) : node(NULL), number_of_Node(0){
    node = new AVLTNode;
    for (int i = 0; i < size; i++)
        this->Insect(arr[i]);
}
AVLT::AVLT(const AVLT &T) : node(NULL), number_of_Node(0){
    *this = T;
}
AVLT::~AVLT(){
    delete node;
}
bool AVLT::empty()const{
    return node == NULL;
}
const AVLT::Element& AVLT::Max()const{
    return node->Max();
}
const AVLT::Element& AVLT::Min()const {
    return node->Min();
}
const AVLT &AVLT::operator = (const AVLT&T){
    delete node;
    node = new AVLTNode;
    number_of_Node = T.number_of_Node;
    *node = *T.node;
    return *this;
}
void AVLT::TraverseFrist(std::ostream& os )const{
    if (node)
        node->nodeTraverseFrist(os);
}
void AVLT::TraverseLast(std::ostream& os )const{
    if (node)
        node->nodeTraverseLast(os);
}
void AVLT::TraverseMid(std::ostream& os )const{
    if (node)
        node->nodeTraverseMid(os);
}
void AVLT::Traverselevel(std::ostream& os )const{
    if (node)
        node->nodeTraverselevel(os);
}
void AVLT::Insect(const AVLT::Element &e){
    number_of_Node++;
    if (node == NULL){
        node = new AVLTNode;
    }
    node->nodeInsect(e);
}
bool AVLT::Delete(const AVLT::Element &e){
    if (node){
        if (node->isLeaf()){
            delete node;
            node = NULL;
        }
        else
            node->nodeDelete(e);
        number_of_Node--;
        return true;
    }
    else{
        return false;
    }
}
int AVLT::Deepth(){
    return node->Deepth;
}
int AVLT::Node(){
    return number_of_Node;
}
const AVLT::AVLTNode*AVLT::find(const AVLT::Element &e)const {
    if (node)
        return node->Find(e);
    else
        return NULL;;
}
std::ostream& operator << (std::ostream& os, const AVLT& T){
    T.TraverseFrist(os);
    return os;
}
const AVLT& find();

这样看上去,AVL树似乎完胜普通的二叉查找树,但是现实是,坏的序列往往很少出现,很多时候,普通二叉树因为不需要判断平衡因子,旋转这些操作,效率反而更高,但是他一旦对上坏的序列就无计可施了,想能防住坏的序列,但又不想每次都旋转,于是就有伸展树这种数据结构,他只在坏的序列出现时旋转,但是只有“坏到一定

程度才旋转”,于是会出现比较坏但坏得不彻底的尴尬情况,伸展树无法保证每次操作都是O(log2N),但是能保证M次操作时间复杂度为O(Mlog2N)。

时间: 2024-11-05 10:33:58

C++类实现AVL树的相关文章

AVL树 冲突链表

;红黑树只不过是AVL树的变种而已 ,平衡方式耕地,意味着比AVL旋转的次数少,长应用于关联数组 红黑树和AVL树在实际开发中比较常用 ;AVL树二叉平衡树 适合在内存中使用速度会达到最优化,要是在文件中那么速度大大降低 ;文件中适合用b+树,B+树读文件一次读的孩子结点比较多,一次read读取尽量多的结点到内存中缓存起来,下次直接从内存中返回. ;百万级别的数据存文件用c库函数利用缓冲区一次不要读两个缓冲区的内容(<4096)设计树的结构,超过就自己设计fopen喽自己做大的缓冲区,降低文件访

图解平衡二叉树,AVL树(一)

图解平衡二叉树,AVL树(一) 学习过了二叉查找树,想必大家有遇到一个问题.例如,将一个数组{1,2,3,4}依次插入树的时候,形成了图1的情况.有建立树与没建立树对于数据的增删查改已经没有了任何帮助,反而增添了维护的成本.而只有建立的树如图2,才能够最大地体现二叉树的优点. 在上述的例子中,图2就是一棵平衡二叉树.科学家们提出平衡二叉树,就是为了让树的查找性能得到最大的体现(至少我是这样理解的,欢迎批评改正).下面进入今天的正题,平衡二叉树. AVL的定义 平衡二叉查找树:简称平衡二叉树.由前

平衡二叉搜索树(AVL树)的原理及实现源代码(有图文详解和C++、Java实现代码)

一.AVL树(平衡二叉搜索树)是什么? AVL树是根据它的发明者G.M. Adelson-Velsky和E.M. Landis命名的.AVL树本质上还是一棵二叉搜索树,它的特点是: 1.本身首先是一棵二叉搜索树. 2.带有平衡条件:每个非叶子结点的左右子树的高度之差的绝对值(平衡因子)最多为1. 例如: 5             5 / \            /  \ 2   6         2   6 / \    \         / \ 1  4   7       1  4

一步一步写平衡二叉树(AVL树)

平衡二叉树(Balanced Binary Tree)是二叉查找树的一个进化体,也是第一个引入平衡概念的二叉树.1962年,G.M. Adelson-Velsky 和 E.M. Landis发明了这棵树,所以它又叫AVL树.平衡二叉树要求对于每一个节点来说,它的左右子树的高度之差不能超过1,如果插入或者删除一个节点使得高度之差大于1,就要进行节点之间的旋转,将二叉树重新维持在一个平衡状态.这个方案很好的解决了二叉查找树退化成链表的问题,把插入,查找,删除的时间复杂度最好情况和最坏情况都维持在O(

AVL树相关操作

#include <iostream> using namespace std; //AVL树的节点 template<typename T> class TreeNode { public: TreeNode() :lson(NULL), rson(NULL), freq(1), hgt(0){} T data;//值 int hgt;//以这个结点为根的树的高度 int freq;//相同点的频率,我是不知道 TreeNode* lson, *rson;//左右儿子的地址 };

二叉树之AVL树的平衡实现(递归与非递归)

这篇文章用来复习AVL的平衡操作,分别会介绍其旋转操作的递归与非递归实现,但是最终带有插入示例的版本会以递归呈现. 下面这张图绘制了需要旋转操作的8种情况.(我要给做这张图的兄弟一个赞)后面会给出这八种情况对应平衡实现. [1] 情况1-2: 这种需要旋转的结构一般称之为LL型,需要右旋 (顺时针旋转). 我用一个图来抽象一下这两个情况,画的不好,我尽量表达吧. 此时需要对A进行平衡操作,方法为: 将A的左子树换为B的右子树. B的右子树换为A. 非递归实现的代码为: 1 void rotate

平衡二叉树之AVL树

AVL树(命名来源于作者姓名,Adelson-Velskii和Landis),即平衡二叉树,满足以下的条件: 1)它的左子树和右子树都是AVL树 2)左子树和右子树的高度差不能超过1 从条件1可能看出是个递归定义. AVL树中任何节点的两个儿子子树的高度最大差别为一,所以它也被称为高度平衡树. AVL树插入节点的步骤,分为2类: 第1类:外侧插入,单旋转 第2类:内侧插入,双旋转(先旋转成外侧插入的情况,再单旋转) 由于调整以后,树高与插入前是相同的,所以无需再向上查看balance情况 代码实

平衡二叉树,AVL树之图解篇

学习过了二叉查找树,想必大家有遇到一个问题.例如,将一个数组{1,2,3,4}依次插入树的时候,形成了图1的情况.有建立树与没建立树对于数据的增删查改已经没有了任何帮助,反而增添了维护的成本.而只有建立的树如图2,才能够最大地体现二叉树的优点.            在上述的例子中,图2就是一棵平衡二叉树.科学家们提出平衡二叉树,就是为了让树的查找性能得到最大的体现(至少我是这样理解的,欢迎批评改正).下面进入今天的正题,平衡二叉树. AVL的定义 平衡二叉查找树:简称平衡二叉树.由前苏联的数学

AVL树的插入操作(旋转)图解

=================================================================== AVL树的概念 在说AVL树的概念之前,我们需要清楚二茬搜索树的概念.对于二叉搜索树,我们知道它可以降低查找速率,但是如果一个二叉搜索树退化成一棵只剩单支的搜索树,此时的查找速率就相当于顺序表中查找元素,效率变低,时间复杂度由原来的O(logN)变为O(N). 此时就有了AVL(高度平衡二叉搜索树),从它的名字就能知道它也是一棵二叉搜索树,只是它在插入元素的时候