简单AVL树

自己写的简单AVL树实现,有BUG或意见欢迎留言

#ifndef SIMPLEAVLTREE_H
#define SIMPLEAVLTREE_H
#include "simplequeue.h"
#include "simplestring.h"
/*关键定义   左右子树高度差绝对值必须小于2
*/
template <typename T>
struct SimpleAvlTreeNode{
    T data;
    int depth;
    SimpleAvlTreeNode *parent;
    SimpleAvlTreeNode *lNode;
    SimpleAvlTreeNode *rNode;
    SimpleAvlTreeNode<T>(T data, int depth, SimpleAvlTreeNode* parent, SimpleAvlTreeNode* lNode, SimpleAvlTreeNode* rNode) :data(data), depth(depth), parent(parent), lNode(lNode), rNode(rNode) {}
};
template <typename T>
class SimpleAvlTree{
protected:
    SimpleAvlTreeNode<T> *root = nullptr;
public:
    //检查深度限制
    bool checkDepthLimit(SimpleAvlTreeNode<T>* currentNode);
    //左旋函数  目的:提升右子节点
    SimpleAvlTreeNode<T>* lRotate(SimpleAvlTreeNode<T> *currentNode);
    //右旋函数  目的:提升左子节点
    SimpleAvlTreeNode<T>* rRotate(SimpleAvlTreeNode<T> *currentNode);
    //更新深度信息
    SimpleAvlTreeNode<T>* updateDepth(SimpleAvlTreeNode<T> *currentNode);
    //增加节点
    void addNode(T data);
    //删除节点
    void removeNode(T data);
    void removeNode(SimpleAvlTreeNode<T>* currentNode);
    //获取根节点
    SimpleAvlTreeNode<T> *getRoot(){ return root; }
    //清除内存占用
    void clear(SimpleAvlTreeNode<T> *n);
    //获取特定节点
    SimpleAvlTreeNode<T>* getNode(T data);
    SimpleAvlTree(){}
    ~SimpleAvlTree(){ clear(root); }
};
//清空占用的空间
template <typename T>
void SimpleAvlTree<T>::clear(SimpleAvlTreeNode<T> *n){
    if(n->lNode != nullptr)clear(n->lNode);
    if(n->rNode != nullptr)clear(n->rNode);
    delete n;
}
//检查深度限制
template <typename T>
bool SimpleAvlTree<T>::checkDepthLimit(SimpleAvlTreeNode<T>* currentNode) {
    int lNodeDepth = currentNode->lNode == nullptr ? 0 : currentNode->lNode->depth;
    int rNodeDepth = currentNode->rNode == nullptr ? 0 : currentNode->rNode->depth;
    int depthOffset = lNodeDepth - rNodeDepth;
    if (depthOffset > 1 || depthOffset < -1)return false;
    else {
        //递归检查子节点
        bool result = true;
        if (currentNode->lNode != nullptr) {
            //检查大小限制
            if (currentNode->lNode->data >= currentNode->data)return false;
            result = checkDepthLimit(currentNode->lNode);
        }
        if (result) {
            if (currentNode->rNode != nullptr) {
                //检查大小限制
                if (currentNode->rNode->data <= currentNode->data)return false;
                result = checkDepthLimit(currentNode->rNode);
            }
            return result;
        }else return false;
    }
}
//右旋函数  目的:提升左子节点
//旋转过后  旋转点的原左节点的左节点深度不变,旋转点的新左节点深度不变,旋转点的深度需要改变,并继续更新
template <typename T>
SimpleAvlTreeNode<T>* SimpleAvlTree<T>::rRotate(SimpleAvlTreeNode<T> *currentNode){
    //std::cout << "右旋" << std::endl;
    //保留旋转点的左节点
    SimpleAvlTreeNode<T> *lNode = currentNode->lNode;
    //当旋转点的左节点的左节点非空,提升左子节点    还要求左节点的右节点为空或者其两个子节点均为空
    if (lNode->lNode != nullptr) {
        if (lNode->rNode == nullptr || (lNode->rNode->lNode == nullptr && lNode->rNode->rNode == nullptr)) {
            //将旋转点的左节点的右节点转为旋转点的左节点
            currentNode->lNode = lNode->rNode;
            if (lNode->rNode != nullptr)lNode->rNode->parent = currentNode;
            //将旋转点的左节点提升到旋转点所在位置
            lNode->parent = currentNode->parent;
            if (currentNode->parent != nullptr) {
                if (currentNode->parent->lNode == currentNode)currentNode->parent->lNode = lNode;
                else currentNode->parent->rNode = lNode;
                //父节点为空说明为root节点
            }
            else this->root = lNode;
            //旋转点成为旋转点的左节点的新右节点
            lNode->rNode = currentNode;
            currentNode->parent = lNode;
            return updateDepth(currentNode);
        }//当旋转点的左节点的左节点非空,且左节点的右节点存在子节点
        //推断   该左节点的右节点只有一个子节点,原因,只要插入一个节点就会导致重平衡  使用该节点替代旋转节点
        else {
            SimpleAvlTreeNode<T>* assistNode = nullptr;
            //当该左节点的右节点的左节点不为空 该左节点的右节点的左节点替代旋转节点
            if (lNode->rNode->lNode != nullptr) {
                assistNode = lNode->rNode->lNode;
                lNode->rNode->lNode = nullptr;
                //该左节点的右节点成为旋转节点的左子节点
                lNode->rNode->parent = currentNode;
                currentNode->lNode = lNode->rNode;
                lNode->rNode = nullptr;
            }//当该左节点的右节点的右节点不为空  该左节点的右节点替代旋转节点
            else {
                assistNode = lNode->rNode;
                lNode->rNode = nullptr;
                //该左节点的右节点的右节点成为旋转节点的左子节点
                assistNode->rNode->parent = currentNode;//因为后面重新赋值了assistNode->rNode,所以不需要置空
                currentNode->lNode = assistNode->rNode;
            }
            //使用该节点替代旋转节点
            assistNode->parent = currentNode->parent;
            if (currentNode->parent != nullptr) {
                if (currentNode->parent->lNode == currentNode)currentNode->parent->lNode = assistNode;
                else currentNode->parent->rNode = assistNode;
            }
            else this->root = assistNode;
            //该左节点和旋转节点分别成为该节点左右节点
            lNode->parent = assistNode;
            assistNode->lNode = lNode;
            currentNode->parent = assistNode;
            assistNode->rNode = currentNode;
            updateDepth(currentNode->lNode);
            updateDepth(currentNode);
            updateDepth(lNode);
            return updateDepth(assistNode);
        }
    }//当旋转点的左节点的左节点为空,提升左子节点的右子节点(此时左子节点的右子节点必不为空)
    else {
        SimpleAvlTreeNode<T>* assistNode = lNode->rNode;
        //左子节点的右子节点提升到旋转点所在位置
        assistNode->parent = currentNode->parent;
        if (currentNode->parent != nullptr) {
            if (currentNode->parent->lNode == currentNode)currentNode->parent->lNode = assistNode;
            else currentNode->parent->rNode = assistNode;
            //父节点为空说明为root节点
        }
        else this->root = assistNode;
        //断开左子节点的右子节点和左子节点的连接  左子节点的右子节点的左子节点成为左子节点的新右子节点,左子节点的右子节点的右子节点成为旋转点的新左子节点
        lNode->rNode = assistNode->lNode;
        if (lNode->rNode != nullptr)lNode->rNode->parent = lNode;
        currentNode->lNode = assistNode->rNode;
        if (currentNode->lNode != nullptr)currentNode->lNode->parent = currentNode;
        //左子节点成为左子节点的右子节点的新左子节点
        assistNode->lNode = lNode;
        lNode->parent = assistNode;
        //旋转点成为左子节点的右子节点的新右子节点
        assistNode->rNode = currentNode;
        currentNode->parent = assistNode;
        updateDepth(currentNode);
        updateDepth(lNode);
        return updateDepth(assistNode);
    }
}
//左旋函数  目的:提升右子节点
//旋转过后  旋转点的原右节点的右节点深度不变,旋转点的新右节点深度不变,旋转点的深度需要改变,并继续更新
template <typename T>
SimpleAvlTreeNode<T>* SimpleAvlTree<T>::lRotate(SimpleAvlTreeNode<T> *currentNode){
    //std::cout << "左旋" << std::endl;
    //保留旋转点的右节点
    SimpleAvlTreeNode<T> *rNode = currentNode->rNode;
    //当旋转点的右节点的右节点非空,提升右子节点    还要求右节点的左节点为空或者其两个子节点均为空
    if (rNode->rNode != nullptr) {
        if (rNode->lNode == nullptr || (rNode->lNode->lNode == nullptr && rNode->lNode->rNode == nullptr)) {
            //将旋转点的右节点的左节点转为旋转点的右节点
            currentNode->rNode = rNode->lNode;
            if (rNode->lNode != nullptr)rNode->lNode->parent = currentNode;
            //将旋转点的右节点提升到旋转点所在位置
            rNode->parent = currentNode->parent;
            if (currentNode->parent != nullptr) {
                if (currentNode->parent->lNode == currentNode)currentNode->parent->lNode = rNode;
                else currentNode->parent->rNode = rNode;
                //父节点为空说明为root节点
            }
            else this->root = rNode;
            //旋转点成为旋转点的右节点的新左节点
            rNode->lNode = currentNode;
            currentNode->parent = rNode;
            return updateDepth(currentNode);
        }//当旋转点的右节点的右节点非空,且右节点的左节点存在子节点
        //推断   该右节点的左节点只有一个子节点,原因,只要插入一个节点就会导致重平衡 使用该节点替代旋转节点
        else {
            SimpleAvlTreeNode<T>* assistNode = nullptr;
            //当该右节点的左节点的左节点不为空 
            if (rNode->lNode->lNode != nullptr) {
                //该右节点的左节点替代旋转节点
                assistNode = rNode->lNode;
                rNode->lNode = nullptr;
                //该右节点的左节点的左节点成为旋转节点的右子节点
                assistNode->lNode->parent = currentNode;//因为后面重新赋值了assistNode->lNode,所以不需要置空
                currentNode->rNode = assistNode->lNode;
            }
            //当该右节点的左节点的右节点不为空 
            else {
                //该右节点的左节点的右节点替代旋转节点
                assistNode = rNode->lNode->rNode;
                rNode->lNode->rNode = nullptr;
                //该右节点的左节点成为旋转节点的右子节点
                rNode->lNode->parent = currentNode;
                currentNode->rNode = rNode->lNode;
                rNode->lNode = nullptr;
            }
            //使用该节点替代旋转节点
            assistNode->parent = currentNode->parent;
            if (currentNode->parent != nullptr) {
                if (currentNode->parent->lNode == currentNode)currentNode->parent->lNode = assistNode;
                else currentNode->parent->rNode = assistNode;
            }
            else this->root = assistNode;
            //该左节点和旋转节点分别成为该节点左右节点
            rNode->parent = assistNode;
            assistNode->rNode = rNode;
            currentNode->parent = assistNode;
            assistNode->lNode = currentNode;
            updateDepth(currentNode->rNode);
            updateDepth(currentNode);
            updateDepth(rNode);
            return updateDepth(assistNode);
        }
    }//当旋转点的右节点的右节点为空,提升右子节点的左子节点(此时右子节点的左子节点必不为空)
    else {
        SimpleAvlTreeNode<T>* assistNode = rNode->lNode;
        //右子节点的左子节点提升到旋转点所在位置
        assistNode->parent = currentNode->parent;
        if (currentNode->parent != nullptr) {
            if (currentNode->parent->lNode == currentNode)currentNode->parent->lNode = assistNode;
            else currentNode->parent->rNode = assistNode;
            //父节点为空说明为root节点
        }
        else this->root = assistNode;
        //断开右子节点的左子节点和右子节点的连接  右子节点的左子节点的左子节点成为旋转点的新右子节点,右子节点的左子节点的右子节点成为右子节点的新左子节点
        currentNode->rNode = assistNode->lNode;
        if (currentNode->rNode != nullptr)currentNode->rNode->parent = currentNode;
        rNode->lNode = assistNode->rNode;
        if (rNode->lNode != nullptr)rNode->lNode->parent = rNode;
        //右子节点成为右子节点的左子节点的新右子节点
        rNode->parent = assistNode;
        assistNode->rNode = rNode;
        //旋转点成为右子节点的左子节点的新左子节点
        currentNode->parent = assistNode;
        assistNode->lNode = currentNode;
        updateDepth(currentNode);
        updateDepth(rNode);
        return updateDepth(assistNode);
    }
}
//更新深度信息
template <typename T>
SimpleAvlTreeNode<T>* SimpleAvlTree<T>::updateDepth(SimpleAvlTreeNode<T> *currentNode){
    int lNodeDepth = currentNode->lNode == nullptr ? 0 : currentNode->lNode->depth;
    int rNodeDepth = currentNode->rNode == nullptr ? 0 : currentNode->rNode->depth;
    int maxDepth = lNodeDepth >= rNodeDepth ? lNodeDepth : rNodeDepth;
    int depthOffset = lNodeDepth - rNodeDepth;
    //左边的深度高出1以上,左旋
    if(depthOffset > 1){
        return rRotate(currentNode);
    }
    else if(depthOffset < -1){
        return lRotate(currentNode);
        //终止条件,当前的depth数据正确并不合理,可能当前节点的depth数据正确但上层的depth数据不正确
        //改为一直更新到根节点
    }
    else {
        currentNode->depth = maxDepth + 1;
        return currentNode->parent;
    }
}
//删除节点
//删除非叶子节点,该节点既有左孩子,又有右孩子。操作:该节点的值替换为该节点的前驱节点(或者后继节点),然后删除前驱节点(或者后继节点)
template <typename T>
void SimpleAvlTree<T>::removeNode(SimpleAvlTreeNode<T>* currentNode) {
    if (currentNode != nullptr) {
        //保留父节点
        SimpleAvlTreeNode<T>* assistNode = currentNode->parent;
        SimpleAvlTreeNode<T>* nextNode = nullptr;
        if (currentNode->lNode != nullptr && currentNode->rNode != nullptr) {
            //找前驱节点
            SimpleAvlTreeNode<T>* frontDriveNode = currentNode->lNode;
            while (frontDriveNode->rNode != nullptr) {
                frontDriveNode = frontDriveNode->rNode;
            }
            //保留currentNode但更新数据信息
            currentNode->data = frontDriveNode->data;
            removeNode(frontDriveNode);
            return;//跳过删除当前节点
        }
        else if (currentNode->lNode != nullptr && currentNode->rNode == nullptr) {
            //如果父节点为空则不需要更新父节点信息  但需要更新root
            if (assistNode != nullptr) {
                //连接需要双向更新
                if (assistNode->lNode == currentNode)assistNode->lNode = currentNode->lNode;
                else assistNode->rNode = currentNode->lNode;
                currentNode->lNode->parent = assistNode;
                //更新父节点深度信息
                nextNode = updateDepth(assistNode);
                while (nextNode != nullptr) {
                    nextNode = updateDepth(nextNode);
                }
            }
            else {
                //连接需要双向更新
                this->root = currentNode->lNode;
                currentNode->lNode->parent = nullptr;
            }
        }//如果某个节点为空,则只要用非空子节点代替被删除的节点
        else if (currentNode->lNode == nullptr && currentNode->rNode != nullptr) {
            //如果父节点为空则不需要更新父节点信息  但需要更新root
            if (assistNode != nullptr) {
                //连接需要双向更新
                if (assistNode->lNode == currentNode)assistNode->lNode = currentNode->rNode;
                else assistNode->rNode = currentNode->rNode;
                currentNode->rNode->parent = assistNode;
                //更新父节点深度信息
                nextNode = updateDepth(assistNode);
                while (nextNode != nullptr) {
                    nextNode = updateDepth(nextNode);
                }
            }
            else {
                //连接需要双向更新
                this->root = currentNode->rNode;
                currentNode ->rNode->parent = nullptr;
            }
        }//如果两个子节点均空,说明为叶子节点,直接删除后更新深度信息
        else {
            //如果父节点为空则不需要更新父节点信息  但需要更新root
            if (assistNode != nullptr) {
                if (assistNode->lNode == currentNode)assistNode->lNode = nullptr;
                else assistNode->rNode = nullptr;
                //更新父节点深度信息
                nextNode = updateDepth(assistNode);
                while (nextNode != nullptr) {
                    nextNode = updateDepth(nextNode);
                }
            }
            else this->root = nullptr;
        }
        //删除当前节点
        delete currentNode;
    }
}
template <typename T>
void SimpleAvlTree<T>::removeNode(T data) {
    if (this->root == nullptr)return ;
    else {
        SimpleAvlTreeNode<T>* node = getNode(data);
        if (node != nullptr)removeNode(node);
    }
}
//获取特定节点
template <typename T>
SimpleAvlTreeNode<T>* SimpleAvlTree<T>::getNode(T data) {
    if (this->root == nullptr)return nullptr;
    else {
        SimpleAvlTreeNode<T>* currentNode = this->root;
        //遍历AVL树,找到匹配的节点
        while (true) {
            if (data == currentNode->data) {
                return currentNode;
            }
            else if (data > currentNode->data) {
                if (currentNode->rNode != nullptr)currentNode = currentNode->rNode;
                else return nullptr;
            }
            else {
                if (currentNode->lNode != nullptr)currentNode = currentNode->lNode;
                else return nullptr;
            }
        }
    }
}
//增加节点
template <typename T>
void SimpleAvlTree<T>::addNode(T data){
    if(this->root == nullptr){//默认单个节点深度为0
        this->root = new SimpleAvlTreeNode<T>(data, 1, nullptr, nullptr, nullptr);
    }else {
        SimpleAvlTreeNode<T> *currentNode = this->root;
        SimpleAvlTreeNode<T>* nextNode = nullptr;
        while(true){
            //比较该数据与当前节点的数值
            if(data >= currentNode->data){
                //如果大于等于且当前节点右值为空,插入
                if(currentNode->rNode == nullptr){
                    currentNode->rNode = new SimpleAvlTreeNode<T>(data, 1, currentNode, nullptr, nullptr);
                    nextNode = updateDepth(currentNode);
                    while (nextNode != nullptr) {
                        nextNode = updateDepth(nextNode);
                    }
                    return ;
                }else currentNode = currentNode->rNode;//如果大于等于但当前节点右值非空,继续比较
            }else {
                //如果大于等于且当前节点左值为空,插入
                if(currentNode->lNode == nullptr){
                    currentNode->lNode = new SimpleAvlTreeNode<T>(data, 1, currentNode, nullptr, nullptr);
                    nextNode = updateDepth(currentNode);
                    while (nextNode != nullptr) {
                        nextNode = updateDepth(nextNode);
                    }
                    return ;
                    //如果大于等于但当前节点左值非空,继续比较
                }else currentNode = currentNode->lNode;
            }
        }
    }
}
class SimpleIntAvlTree : public SimpleAvlTree<int>{
public:
    void iteratorTreeString(SimpleAvlTreeNode<int> *currentNode);
    char *toString();
    char *depthToString();
    SimpleIntAvlTree(){}
    ~SimpleIntAvlTree(){}
};
void SimpleIntAvlTree::iteratorTreeString(SimpleAvlTreeNode<int> *currentNode){
    if(currentNode->lNode != nullptr)iteratorTreeString(currentNode->lNode);
    std::cout << currentNode->data;
    if(currentNode->rNode != nullptr)iteratorTreeString(currentNode->rNode);
}
char *SimpleIntAvlTree::toString(){
    if (root == nullptr) {
        SimpleString str = SimpleString("空树");
        return str.getData();
    }
    SimpleQueue<SimpleAvlTreeNode<int> *> *ss = new SimpleQueue<SimpleAvlTreeNode<int> *>();
    SimpleQueue<SimpleAvlTreeNode<int> *> *ssNext = new SimpleQueue<SimpleAvlTreeNode<int> *>();
    SimpleQueue<SimpleAvlTreeNode<int> *> *temp = nullptr;
    SimpleAvlTreeNode<int> *n = nullptr;
    ss->push(root);
    SimpleStringBuilder strBuilder;
    SimpleString layerInsideGap = SimpleString(" ");
    SimpleString layerGap = SimpleString("\n");
    while(true){
        while(!ss->isEmpty()){
            n = ss->pop_back();
            if(n->lNode != nullptr)ssNext->push(n->lNode);
            if(n->rNode != nullptr)ssNext->push(n->rNode);
            SimpleString data = SimpleString((long)n->data);
            strBuilder.append(layerInsideGap);
            strBuilder.append(data);
        }
        if(!ssNext->isEmpty()){
            temp = ss;
            ss = ssNext;
            ssNext = temp;
            strBuilder.append(layerGap);
        }else break;
    }
    int length = strBuilder.getLength();
    char *s = new char[length + 1];
    memcpy(s, strBuilder.getData(), length);
    s[length] = 0;
    //释放空间
    delete ss;
    delete ssNext;
    return s;
}
char *SimpleIntAvlTree::depthToString(){
    if (root == nullptr) {
        SimpleString str = SimpleString("空树");
        return str.getData();
    }
    SimpleQueue<SimpleAvlTreeNode<int> *> *ss = new SimpleQueue<SimpleAvlTreeNode<int> *>();
    SimpleQueue<SimpleAvlTreeNode<int> *> *ssNext = new SimpleQueue<SimpleAvlTreeNode<int> *>();
    SimpleQueue<SimpleAvlTreeNode<int> *> *temp = nullptr;
    SimpleAvlTreeNode<int> *n = nullptr;
    ss->push(root);
    SimpleStringBuilder strBuilder;
    SimpleString layerInsideGap = SimpleString(" ");
    SimpleString layerGap = SimpleString("\n");
    while(true){
        while(!ss->isEmpty()){
            n = ss->pop_back();
            if(n->lNode != nullptr)ssNext->push(n->lNode);
            if(n->rNode != nullptr)ssNext->push(n->rNode);
            SimpleString data = SimpleString((long)n->depth);
            strBuilder.append(layerInsideGap);
            strBuilder.append(data);
        }
        if(!ssNext->isEmpty()){
            temp = ss;
            ss = ssNext;
            ssNext = temp;
            strBuilder.append(layerGap);
        }else break;
    }
    int length = strBuilder.getLength();
    char *s = new char[length + 1];
    memcpy(s, strBuilder.getData(), length);
    s[length] = 0;
    //释放空间
    delete ss;
    delete ssNext;
    return s;
}
#endif // SIMPLEAVLTREE_H

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蔡海航

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值