首页 文章

balancer 二叉搜索树(BST)

提问于
浏览
5

我正在尝试创建一个balance_bst(bstNode root)函数,但我正在努力实现 .

我正在将该函数实现为模板函数,因为我的bstNode类是一个模板类 .

这是(部分)我的代码:

template<class Item, class  Key>
class bstNode{
public:
    //Constructor
    bstNode(const Item& init_data = Item(), const Key& init_key = Key(), bstNode<Item, Key>* l_child = NULL, bstNode<Item, Key>* r_child = NULL){
        data_field = init_data;
        key_field = init_key;
        l_ptr = l_child;
        r_ptr = r_child;
    }
    //Destructor
    ~bstNode(){
        data_field = 0;
        key_field = 0;
        l_ptr = r_ptr = NULL;
    }
    //Basic Member Functions
    bstNode<Item, Key>*& left( )   {                    return l_ptr;       }           //returns left child pointer by reference
    bstNode<Item, Key>*& right( )  {                    return r_ptr;       }           //returns right child pointer by reference
    bstNode<Item, Key>* left( ) const   {               return l_ptr;       }       //returns left child pointer by reference
    bstNode<Item, Key>* right( ) const  {               return r_ptr;       }       //returns right child pointer by reference
    const Item& data() const{                           return data_field;  }           //returns reference to data_field
    const Key& key()const {                             return key_field;   }
    Item& data() {                                      return data_field;  }           //returns reference to data_field
    Key& key() {                                        return key_field;   }
    void set_data(const Item& new_data){            data_field = new_data;      }       //sets data_field to new_data
    void set_key(const Key& new_key){               key_field = new_key;        }       //sets key_field to new_key
    void set_left(bstNode* new_left){               l_ptr = new_left;           }       //sets left child pointer to new_left
    void set_right(bstNode* new_right){             r_ptr = new_right;          }       //sets right child pointer to new_right

private:
    bstNode<Item, Key>  *l_ptr,     //pointer to left child node 
                        *r_ptr;     //pointer to right child node
    Item    data_field;
    Key     key_field;
};

template<class Item, class Key>
void balance_bst(bstNode<Item, Key>*& root){                //unfinished

    std::vector< bstNode<Item, Key>* > nodes;
    sorter(root, nodes);
    size_t i = nodes.size()/2;                      //size() divided by 2 will yield
                                                    //index of middle element of vector for 
                                                    //odd-isized arrays and the greater of the 
                                                    //middle two elements for an even-sized array

    while(i>=0){
        root->set_key(nodes[i]->key());                             
        root->set_data(nodes[i]->data());
         //.....MORE CODE HERE: recursive call??

    }


}

template<class Item, class Key>
void sorter(bstNode<Item, Key>*& root, std::vector<bstNode<Item, Key>* >& tree_nodes){
    if(root == NULL)
        return;
    sorter(root->left(), tree_nodes);
    tree_nodes.push_back(root);
    sorter(root->right(), tree_nodes); 
}

我一直在搞乱实际的balance_bst函数,并认为递归是明显的解决方案,但我似乎无法绕过这个...

sorter基本上使用inorder处理算法将BST的元素插入到矢量中 . 因此,只要“root”是指向二叉搜索树的根的指针(即节点左子树的所有键值都小于节点的键值,并且节点右子树的所有键值都大于然后,插入到向量中的节点将以升序方式进行分类 .

然后,为了创建一个 balancer 的树,我将节点插入树的根处的向量的中心,然后应该能够递归地插入左和右子节点,然后这些节点将位于左半部的中间向量和向量的右半部分的中间 .

注意:据我所知,这是使用整数除法,即7/2 = 3,这将是大小为7的数组的中间元素的索引 . 对于偶数大小的数组,上面实现的算法将找到向量中间两个元素中较大者的索引 .

无论如何,欢迎并鼓励任何建议或观察!提前致谢 .

编辑:我要问的是如何实现一个功能来 balancer 二叉搜索树? ( balancer 的BST是指给定节点数量的最小深度 . )

1 回答

  • 7

    balancer 二叉搜索树也称为AVL树 .

    This wikipedia link对解决 balancer 问题有很好的解释 .

    我发现在插入过程中 balancer 树的最简单方法 . 这是一个带有辅助函数(用于各种旋转情况)和AVLNode类的递归插入 .

    bool avl_insert(AVLNode*& subRoot, const int &newData, bool &taller)
            {
                bool result = true;
                if(!subRoot){
                    subRoot = new AVLNode(newData);
                    taller = true;
                }
                else if(newData == subRoot->getData()){
                    result = false;
                    taller = false;
                }
                else if(newData < subRoot->getData()){
                    result = avl_insert(subRoot->getLeft(), newData, taller);
                    if(taller)
                        switch(subRoot->getBalance()){
                        case -1:
                            left_balance(subRoot);
                            taller = false;
                            break;
                        case 0:
                            subRoot->setBalance(-1);
                            break;
                        case 1:
                            subRoot->setBalance(0);
                            taller = false;
                            break;
                        }
                }
                else{
                    result = avl_insert(subRoot->getRight(), newData, taller);
                    if(taller)
                        switch(subRoot->getBalance()){
                        case -1:
                            subRoot->setBalance(0);
                            taller = false;
                            break;
                        case 0:
                            subRoot->setBalance(1);
                            break;
                        case 1:
                            right_balance(subRoot);
                            taller = false;
                            break;
                        }
                }
                return result;
            }
    

    助手功能

    void right_balance(AVLNode *&subRoot)
            {
                AVLNode *&right_tree = subRoot->getRight();
                switch(right_tree->getBalance()){
                case 1:
                    subRoot->setBalance(0);
                    right_tree->setBalance(0);
                    rotate_left(subRoot); break;
                case 0:
                    cout<<"WARNING: program error in right_balance"<<endl; break;
                case -1:
                    AVLNode *subTree = right_tree->getLeft();
                    switch(subTree->getBalance()){
                        case 0:
                            subRoot->setBalance(0);
                            right_tree->setBalance(0);break;
                        case -1:
                            subRoot->setBalance(0);
                            right_tree->setBalance(1); break;
                        case 1:
                            subRoot->setBalance(-1);
                            right_tree->setBalance(0);break;
                    }
                    subTree->setBalance(0);
                    rotate_right(right_tree);
                    rotate_left(subRoot); break;
                }
            }
            void left_balance(AVLNode *&subRoot)
            {
                AVLNode *&left_tree = subRoot->getLeft();
                switch(left_tree->getBalance()){
                case -1:
                    subRoot->setBalance(0);
                    left_tree->setBalance(0);
                    rotate_right(subRoot); break;
                case 0:
                    cout<<"WARNING: program error in left_balance"<<endl; break;
                case 1:
                    AVLNode *subTree = left_tree->getRight();
                    switch(subTree->getBalance()){
                        case 0:
                            subRoot->setBalance(0);
                            left_tree->setBalance(0);break;
                        case -1:
                            subRoot->setBalance(0);
                            left_tree->setBalance(1); break;
                        case 1:
                            subRoot->setBalance(-1);
                            left_tree->setBalance(0);break;
                    }
                    subTree->setBalance(0);
                    rotate_left(left_tree);
                    rotate_right(subRoot); break;
                }
            }
    
        void rotate_left(AVLNode *&subRoot)
        {
            if(subRoot == NULL || subRoot->getRight() == NULL)
                cout<<"WARNING: program error detected in rotate_left"<<endl;
            else{
                AVLNode *right_tree = subRoot->getRight();
                subRoot->setRight(right_tree->getLeft());
                right_tree->setLeft(subRoot);
                subRoot = right_tree;
            }
        }
        void rotate_right(AVLNode *&subRoot)
        {
            if(subRoot == NULL || subRoot->getLeft() == NULL)
                cout<<"WARNING: program error detected in rotate_left"<<endl;
            else{
                AVLNode *left_tree = subRoot->getLeft();
                subRoot->setLeft(left_tree->getRight());
                left_tree->setRight(subRoot);
                subRoot = left_tree;
            }
        }
    

    AVLNode类

    class AVLNode
    {
      public:
            AVLNode()
            {
                previous = NULL;
                next = NULL;
            }
            AVLNode(int newData){
                data = newData;
                previous = NULL;
                balance=0;
                next = NULL;
            }
            ~AVLNode(){}
            void setBalance(int b){balance = b;}
            int getBalance(){return balance;}
            void setRight(AVLNode* newNext){next = newNext;}
            void setLeft(AVLNode* newPrevious){previous = newPrevious;}
            AVLNode* getRight() const{return next;}
            AVLNode* getLeft() const{return previous;}
            AVLNode*& getRight(){return next;}
            AVLNode*& getLeft(){return previous;}
            int getData() const{return data;}
            int& getData(){return data;}
            void setData(int newData){data = newData;}
            void setHeight(int newHeight){ height = newHeight;}
            int getHeight(){return height;}
      private:
            AVLNode* next;
            AVLNode* previous;
            int balance;
            int height;
            int data;
    };
    

    希望这可以帮助!

相关问题