微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

C ++平衡AVL树

如何解决C ++平衡AVL树

我正在用c ++实现bst,更确切地说是AVL树。除了平衡以外,我几乎可以进行所有工作。当程序尝试平衡LR或RL时,它将崩溃。例如,如果在我插入7、5、6或7、9、8时崩溃,但是它将与:7、6、5和7、8、9一起工作。

相关代码(pastebin):https://pastebin.com/cn69XLn5

相关代码

//RIGHT RIGHT ROTATION
template <typename x_type>
typename AVLTree<x_type>::bstNode* AVLTree<x_type>::RRrotation(bstNode* rootptr)
{
    bstNode* temp;
    temp = rootptr->rightChild;
    rootptr->rightChild = temp->leftChild; 
    temp->leftChild = rootptr;              
 
    return temp;
}
 
//LEFT LEFT ROTATION
template <typename x_type>
typename AVLTree<x_type>::bstNode* AVLTree<x_type>::LLrotation(bstNode* rootptr)
{
    bstNode* temp;
    temp = rootptr->leftChild;
    rootptr->leftChild = temp->rightChild;
    temp->rightChild = rootptr;
 
    return temp;
}
 
//LEFT RIGHT ROTATION
template <typename x_type>
typename AVLTree<x_type>::bstNode* AVLTree<x_type>::LRrotation(bstNode* rootptr)
{
    bstNode* temp;
    temp = rootptr->leftChild;
    rootptr->leftChild = RRrotation(temp);
 
    return LLrotation(rootptr);
}
 
//RIGHT LEFT ROTATION
template <typename x_type>
typename AVLTree<x_type>::bstNode* AVLTree<x_type>::RLrotation(bstNode* rootptr)
{
    bstNode* temp;
    temp = rootptr->rightChild;
    rootptr->rightChild = LLrotation(temp);
 
    return RRrotation(rootptr);
}
 
// There are four different rotation scenarios,two simpler and two harder.
// check what rotation is needed and then send forward to that rotation
template <typename x_type>
typename AVLTree<x_type>::bstNode* AVLTree<x_type>::balanceFactory(bstNode* rootptr)
{
    //std::cout << rootptr->value << std::endl;
    int BF = balanceFactor();
    if (BF > 1) //use == 2 instead?
    {
        if (balanceFactorLeftChild() > 0) //perform left left rotation
        {
            rootptr = LLrotation(rootptr);
        }else                                 //perform left right rotation
        {
            rootptr = LRrotation(rootptr);
        }
    }
    else if (BF < -1)
    {
        if (balanceFactorRightChild() > 0)  // perform right left rotation
        {
            rootptr = RLrotation(rootptr);
        }else
        {
            rootptr = RRrotation(rootptr);  // the last option,which is right right rotation
        }
    }
    return rootptr;
}
 
template <typename x_type>
void AVLTree<x_type>::insert(x_type value){
    insert(&(this->rootptr),value);
}
 
template <typename x_type>
void AVLTree<x_type>::insert(bstNode** rootptr,x_type value)
{
    if (*rootptr == nullptr)
    {
        //this tree is empty
        *rootptr = createNewNode(value);
    }
 
    else if ((*rootptr)->value == value) //if value already in tree,dont insert again,just break
    {
        return;
 
    }else if (value <= (*rootptr)->value)
    {
        //insert at left side using recursion
        insert(&(*rootptr)->leftChild,value);
        *rootptr = balanceFactory(*rootptr);
 
    }else if (value >= (*rootptr)->value)
    {
        //insert at right side using recursion
        insert(&(*rootptr)->rightChild,value);
        *rootptr = balanceFactory(*rootptr);
 
 
    }
}

所有代码(pastebin):https://pastebin.com/uxTQ369i

所有代码

//avl tree emil wallin
#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>

template <typename x_type>
class AVLTree {
    struct bstNode {
        x_type value;
        bstNode* leftChild;
        bstNode* rightChild;
    };
    //bstNode* rootptr;

public:
    AVLTree();
    bstNode* createNewNode(x_type value);
    int balanceFactor();
    int balanceFactorLeftChild();
    int balanceFactorRightChild();
    bstNode* RRrotation(bstNode* rootptr);
    bstNode* LLrotation(bstNode* rootptr);
    bstNode* LRrotation(bstNode* rootptr);
    bstNode* RLrotation(bstNode* rootptr);
    bstNode* balanceFactory(bstNode* rootptr);
    void insert(x_type value);
    void remove(x_type value);
    bool find(x_type value);
    std::vector<x_type>preOrderWalk();
    std::vector<x_type>inorderWalk();
    std::vector<x_type>postorderWalk();
    x_type getMin();
    x_type getMax();
    x_type maxVal(x_type a,x_type b);
    size_t getTreeHeight();
    bstNode* get_rootptr(){return rootptr;}


private:
    bstNode* rootptr;
    int balanceFactor(bstNode* rootptr);
    void insert(bstNode** rootptr,x_type value);
    void remove(bstNode*,x_type value);
    bool find(bstNode* rootptr,x_type value);
    std::vector<x_type> preOrderWalk(bstNode* rootptr);
    std::vector<x_type> inorderWalk(bstNode* rootptr);
    std::vector<x_type> postorderWalk(bstNode* rootptr);
    x_type getMin(bstNode* rootptr);
    x_type getMax(bstNode* rootptr);
    size_t getTreeHeight(bstNode* rootptr);
};



//this is a constructor:
template <typename x_type>
AVLTree<x_type>::AVLTree()
{
    this->rootptr = nullptr;
}

//dynamically allocate new memory for a node,using keyword new
template <typename x_type>
typename AVLTree<x_type>::bstNode* AVLTree<x_type>::createNewNode(x_type value)
{
    bstNode* newNode = new bstNode();
    (*newNode).value = value;
    newNode->leftChild = nullptr;
    newNode->rightChild = nullptr;

    return newNode;
}
template <typename x_type>
int AVLTree<x_type>::balanceFactorLeftChild()
{
    return balanceFactor(this->rootptr->leftChild);
}

template <typename x_type>
int AVLTree<x_type>::balanceFactorRightChild()
{
    return balanceFactor(this->rootptr->rightChild);
}

template <typename x_type>
int AVLTree<x_type>::balanceFactor()
{
    return balanceFactor(this->rootptr);
}
template <typename x_type>
int AVLTree<x_type>::balanceFactor(bstNode* rootptr)
{
    int leftHeight = getTreeHeight(rootptr->leftChild);
    int rightHeight = getTreeHeight(rootptr->rightChild);
    int balanceNumber = leftHeight - rightHeight;

    return balanceNumber;
}


//RIGHT RIGHT ROTATION
template <typename x_type>
typename AVLTree<x_type>::bstNode* AVLTree<x_type>::RRrotation(bstNode* rootptr)
{
    bstNode* temp;
    temp = rootptr->rightChild;
    rootptr->rightChild = temp->leftChild; 
    temp->leftChild = rootptr;              
    
    return temp;
}

//LEFT LEFT ROTATION
template <typename x_type>
typename AVLTree<x_type>::bstNode* AVLTree<x_type>::LLrotation(bstNode* rootptr)
{
    bstNode* temp;
    temp = rootptr->leftChild;
    rootptr->leftChild = temp->rightChild;
    temp->rightChild = rootptr;

    return temp;
}

//LEFT RIGHT ROTATION
template <typename x_type>
typename AVLTree<x_type>::bstNode* AVLTree<x_type>::LRrotation(bstNode* rootptr)
{
    bstNode* temp;
    temp = rootptr->leftChild;
    rootptr->leftChild = RRrotation(temp);

    return LLrotation(rootptr);
}

//RIGHT LEFT ROTATION
template <typename x_type>
typename AVLTree<x_type>::bstNode* AVLTree<x_type>::RLrotation(bstNode* rootptr)
{
    bstNode* temp;
    temp = rootptr->rightChild;
    rootptr->rightChild = LLrotation(temp);
    
    return RRrotation(rootptr);
}

// There are four different rotation scenarios,which is right right rotation
        }
    }
    return rootptr;
}

template <typename x_type>
void AVLTree<x_type>::insert(x_type value){
    insert(&(this->rootptr),value);
}

template <typename x_type>
void AVLTree<x_type>::insert(bstNode** rootptr,x_type value)
{
    if (*rootptr == nullptr)
    {
        //this tree is empty
        *rootptr = createNewNode(value);
    }

    else if ((*rootptr)->value == value) //if value already in tree,just break
    {
        return;

    }else if (value <= (*rootptr)->value)
    {
        //insert at left side using recursion
        insert(&(*rootptr)->leftChild,value);
        *rootptr = balanceFactory(*rootptr);

    }else if (value >= (*rootptr)->value)
    {
        //insert at right side using recursion
        insert(&(*rootptr)->rightChild,value);
        *rootptr = balanceFactory(*rootptr);
        
        
    }
}

template <typename x_type>
void AVLTree<x_type>::remove(x_type value)
{
    remove(this->rootptr,value);
}

template <typename x_type>
void AVLTree<x_type>::remove(bstNode* rootptr,x_type value)
{
    if (rootptr == nullptr)
    {
        return; //there is no data in tree
    } else if (value > rootptr->value) // go to right subtree
    {
        remove(rootptr->rightChild,value);
    } else if (value < rootptr->value) // go to left subtree
    {
        remove(rootptr->leftChild,value);
    }
    else // if its not greater nor less,it must be equal,therefore we found the node to be removed
    {
        //there are three different situations.
        //the node we must remove can have 0 children -> 1.
        //the node we must remove can have 1 child -> 2.
        //the node we must remove can have 2 children -> 3.

        //1:
        if (rootptr->leftChild == nullptr && rootptr->rightChild == nullptr)
        {
            delete rootptr;
            rootptr = nullptr;
        }

        //2:
        else if (rootptr->leftChild == nullptr)
        {
            bstNode* tempPtr = rootptr;
            rootptr = rootptr->rightChild;
            delete tempPtr;
        }

        //2 (other child):
        else if (rootptr->rightChild == nullptr)
        {
            bstNode* tempPtr = rootptr;
            rootptr = rootptr->leftChild;
            delete tempPtr;
        }

        //3:
        else
        {
            //bstNode<x_type>* tempPtr = getMin(rootptr->rightChild);
            bstNode* tempPtr = rootptr;
            tempPtr->value = getMax(rootptr->leftChild);

            rootptr->value = tempPtr->value;
            remove(rootptr->leftChild,tempPtr->value);
        }
    }
    return;
}

template <typename x_type>
bool AVLTree<x_type>::find(x_type value)
{
    return find(this->rootptr,value);
}
template <typename x_type>
bool AVLTree<x_type>::find(bstNode* rootptr,x_type value)
{
    if (rootptr == nullptr)
    {
        //either the tree is empty
        return false;
    }else if (rootptr->value == value)
    {
        //value found
        return true;
    }else if (value <= rootptr->value)
    {
        return find(rootptr->leftChild,value);
    }else if (value >= rootptr->value)
    {
        return find(rootptr->rightChild,value);
    }

    return false;
}
template <typename x_type>
std::vector<x_type> AVLTree<x_type>::preOrderWalk(){
    return preOrderWalk(this->rootptr);
}
template <typename x_type>
std::vector<x_type> AVLTree<x_type>::preOrderWalk(bstNode* rootptr)
{
    std::vector<x_type> preOrderVec;
    if (rootptr != nullptr)
    {
        std::vector<x_type> temp;

        preOrderVec.push_back(rootptr->value);
        if (rootptr->leftChild != nullptr)
        {
            temp = preOrderWalk(rootptr->leftChild); //mästarns notering
            preOrderVec.insert(preOrderVec.end(),temp.begin(),temp.end());
        }
        if (rootptr->rightChild != nullptr)
        {
            temp = preOrderWalk(rootptr->rightChild);
            preOrderVec.insert(preOrderVec.end(),temp.end());
        }
    }
    return preOrderVec;
}

template <typename x_type>
std::vector<x_type> AVLTree<x_type>::inorderWalk(){
    return inorderWalk(this->rootptr);
}
template <typename x_type>
std::vector<x_type> AVLTree<x_type>::inorderWalk(bstNode* rootptr)
{
    std::vector<x_type> inorderVec;
    if (rootptr != nullptr)
    {
        std::vector<x_type> temp;

        if (rootptr->leftChild != nullptr)
        {
            temp = inorderWalk(rootptr->leftChild); //mästarns notering
            inorderVec.insert(inorderVec.end(),temp.end());
        }
        inorderVec.push_back(rootptr->value);
        if (rootptr->rightChild != nullptr)
        {
            temp = inorderWalk(rootptr->rightChild);
            inorderVec.insert(inorderVec.end(),temp.end());
        }
    }
    return inorderVec;
}

template <typename x_type>
std::vector<x_type> AVLTree<x_type>::postorderWalk(){
    return postorderWalk(this->rootptr);
}
template <typename x_type>
std::vector<x_type> AVLTree<x_type>::postorderWalk(bstNode* rootptr)
{
    std::vector<x_type> postorderVec;
    if (rootptr != nullptr)
    {
        std::vector<x_type> temp;

        if (rootptr->leftChild != nullptr)
        {
            temp = postorderWalk(rootptr->leftChild); //mästarns notering
            postorderVec.insert(postorderVec.end(),temp.end());
        }
        if (rootptr->rightChild != nullptr)
        {
            temp = postorderWalk(rootptr->rightChild);
            postorderVec.insert(postorderVec.end(),temp.end());
        }
        postorderVec.push_back(rootptr->value);
    }
    return postorderVec;
}

template <typename x_type>
x_type AVLTree<x_type>::getMin()
{
    return (getMin(this->rootptr));
}
template <typename x_type>
x_type AVLTree<x_type>::getMin(bstNode* rootptr)
{
    if (rootptr == nullptr) //empty tree
    {
        std::cout << "No minimum because the tree is empty" << std::endl;
    }

    else if(rootptr->leftChild == nullptr) //the node that has no leftChild must be the last we want to search
    {
        return rootptr->value;
    }

    return getMin(rootptr->leftChild);

}
template <typename x_type>
x_type AVLTree<x_type>::getMax()
{
    return getMax(this->rootptr);
}
template <typename x_type>
x_type AVLTree<x_type>::getMax(bstNode* rootptr)
{
    if (rootptr == nullptr) // empty tree
    {
        std::cout << "No maximum because the tree is empty" << std::endl;
    }

    else if(rootptr->rightChild == nullptr) //the node that has no rightChild must be the last we want to search
    {
        return rootptr->value;
    }

    return getMax(rootptr->rightChild);
}

template <typename x_type>
x_type AVLTree<x_type>::maxVal(x_type a,x_type b)
{
    if (a > b) return a;
    else return b;
}

template <typename x_type>
size_t AVLTree<x_type>::getTreeHeight()
{
    return getTreeHeight(this->rootptr);
}
template <typename x_type>
size_t AVLTree<x_type>::getTreeHeight(bstNode* rootptr)
{
    int height;
    int leftHeight;
    int rightHeight;

    if (rootptr == nullptr) return -1;

    leftHeight = getTreeHeight(rootptr->leftChild);
    rightHeight = getTreeHeight(rootptr->rightChild);

    height = (maxVal(leftHeight,rightHeight));
    height += 1;
    //static_cast<size_t>(height);

    return height;
}

int main()
{
    AVLTree<int>* avlTreeobject = new AVLTree<int>();
    
    avlTreeobject->insert(7);
    avlTreeobject->insert(6);
    avlTreeobject->insert(5);
   
    std::cout << "\n actual root: " << (avlTreeobject->get_rootptr()->value);
    std::cout << "\n actual root->leftchild: " << (avlTreeobject->get_rootptr()->leftChild->value);
    std::cout << "\n actual root->rightchild: " << (avlTreeobject->get_rootptr()->rightChild->value);
    

    std::cin.get();
    std::getchar();
    return 0;
}

我不确定,但是我认为问题是我向该函数发送了错误的节点,因此它崩溃,因为它假定正在发送的节点将有一个子节点,但不会,因此它尝试访问nullptr。我不知道该如何解决

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。