将BST(无递归)转换为AVL时的旋转问题

时间:2013-11-24 15:32:58

标签: c++ binary-search-tree avl-tree

本周末我正在研究大学项目(数据结构),我必须用C ++编写AVL树代码。我认为先编码BST然后将其转换为AVL并不困难。可能我错了......我有两个类,类节点和类AVLTree,它是类节点的朋友。我设法根据BST的规则(我检查)进行插入和删除,并且我设法找到树的节点的平衡因子(这也有效)。然而,当我尝试简单的左旋转时,一切都发生了故障!这是我的代码(首先是.h文件):

class node
{
public:
    node();
private:
    int data;
    int heightL;
    int heightR;
    int balance;
    node* leftChild;
    node* rightChild;
    friend class AVLTree; //Only class AVLTree has now access to the private fields of     class node
};
class node;

class AVLTree
{
public:
    AVLTree();
    bool insertNode(int aData);
    node* searchNode(int key);
    bool deleteNode(int key);
    node* findMostLeft(node *aRoot);
    node* findMostRight(node *subtree);
    void display();
private:
    node *root;
    void inOrderTraversal(node* pointer);
    node* newNode(int aData);
    void updateHeightsInserting(int nodeCounter,int aData);
    void updateHeightsDeleting(int nodeCounter,int aData);
    void updateTreeHeights(node *ptr);
    int max(int a,int b);
    void balanceTree(node *current,node *previous,node *next);
    void slRotation(node* current,node *previous,node *next);
    void srRotation(node* current,node *previous,node *next);
    void dlRotation(node* current,node *previous,node *next);
    void drRotation(node* current,node *previous,node *next);

};

现在是AVLTree类的.cpp文件(仅限某些方法)

bool AVLTree::insertNode(int aData)
{
node *current,*next,*ptr;
bool isLeftChild;
int nodeCounter=0;
current=next=root;
ptr=newNode(aData);
if(ptr==NULL) //Couldn't allocate memory
{
    return false;
}
if(current==NULL) //Inserting the first node in our tree (root==NULL)
{
    root=ptr;
    return true; //Successful insertion of root
}
do
{
    if(aData<current->data) //If the node we want to insert has data smaller than the current node's data, then repeat the procedure for the left child of the current node
    {
        next=current->leftChild;
        isLeftChild=true;
        nodeCounter++;
    }
    else if(aData>current->data) //If the node we want to insert has data bigger than the current node's data, then repeat the procedure for the right child of the current node
    {
        next=current->rightChild;
        isLeftChild=false;
        nodeCounter++;
    }
    if(next==NULL)
    {
        if(isLeftChild)
        {
            current->leftChild=ptr;
        }
        else
        {
            current->rightChild=ptr;
        }
        updateHeightsInserting(nodeCounter,aData);
        return true;
    }
    current=next; //Repeat the procedure for the next node
}while(next!=NULL); //Repeat the procedure until there's no next node, meaning we enter the if(next==NULL) statement
}

更新高度的方法:

void AVLTree::updateHeightsInserting(int nodeCounter,int aData)
{
node *current,*next,*previous;
current=next=previous=root;
do
{
    if(aData<current->data)
    {
        if(current->heightL<nodeCounter)
        {
            current->heightL=nodeCounter;
        }
        next=current->leftChild;
        nodeCounter--;
    }
    else if(aData>current->data)
    {
        if(current->heightR<nodeCounter)
        {
            current->heightR=nodeCounter;
        }
        next=current->rightChild;
        nodeCounter--;
    }
    current->balance=current->heightR-current->heightL;
    if(abs(current->balance)>1)
    {
        if(abs(next->heightR-next->heightL)<1) //We use <1, because the hight of the next node hasn't been increased yet-If the next node isn't problematic it means the current node is
            balanceTree(current,previous,next);
    }
    previous=current;
    current=next;
}while(next->data!=aData);
}

轮换试用代码(不起作用!)

void AVLTree::slRotation(node *current,node *previous,node *next)
{
if(current==root) //previous=current
{
   node *temp;
   root=next; //next=current->rightChild
   temp=next->leftChild;
   next->leftChild=current;
   current->rightChild=temp;
}
else
    previous->rightChild=next;
    current->rightChild=NULL;
    next->leftChild=current;
} 

和Balancing方法:

void AVLTree::balanceTree(node *current,node *previous,node *next)
{
if(current->balance>1) //if the tree is right heavy
    if(next->balance>0) //if the tree's right subtree is right heavy
        slRotation(current,previous,next); //perform Simple Left Rotation
    else //if the tree's right subtree is left heavy
        dlRotation(current,previous,next); //perform Double Left Rotation
else //if the tree is left heavy
    if(next->balance<0) //if the tree's left subtree is left heavy
        srRotation(current,previous,next); //perform Simple Right Roation
    else //if the tree's left subtree is right heavy
        drRotation(current,previous,next); //perform Double Right Rotation
updateTreeHeights(root);
}

我也使用updateTreeHeights(这也经过了测试,并且在没有旋转的情况下运行良好)这里的方法效率不高,我知道,但我没有更好的主意!

void AVLTree::updateTreeHeights(node *ptr)  //Visits the nodes by level recursively      (post-order traversal), so that it can calculate the balance of each node
{
if(ptr==NULL)
    return;
updateTreeHeights(ptr->leftChild);
updateTreeHeights(ptr->rightChild);
if(ptr->leftChild==NULL && ptr->rightChild==NULL)
{
    ptr->heightL=ptr->heightR=0;
}
else if(ptr->leftChild==NULL)
{
    ptr->heightR=max(ptr->rightChild->heightL,ptr->rightChild->heightR)+1;
    ptr->heightL=0;
}
else if(ptr->rightChild==NULL)
{
    ptr->heightL=max(ptr->leftChild->heightL,ptr->leftChild->heightR)+1;
    ptr->heightR=0;
}
else
{
    ptr->heightL=max(ptr->leftChild->heightL,ptr->leftChild->heightR)+1;
    ptr->heightR=max(ptr->rightChild->heightL,ptr->rightChild->heightR)+1;
}
ptr->balance=ptr->heightR-ptr->heightL;
}

对不起,很长的帖子!这是我生命中第一次使用AVL树,更不用说编程了!希望你能帮忙!

1 个答案:

答案 0 :(得分:0)

问题解决了!我用双转的左右指针搞砸了!