6

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関数をいじっていて、再帰が明らかな解決策だと思いますが、これに頭を悩ませているようには見えません...

ソーターは基本的に、順序処理アルゴリズムを使用してBSTの要素をベクトルに挿入します。「ルート」が二分探索木のルートへのポインタである限り(つまり、ノードの左側のサブツリーのすべてのキー値がノードのキー値よりも小さく、ノードの右側のサブツリーのすべてのキー値がノード)次に、ベクトルに挿入されたノードは昇順でソーターになります。

次に、バランスの取れたツリーを作成するために、ツリーのルートにあるベクトルの中央にノードを挿入します。次に、左半分の中央にある左右の子ノードを再帰的に挿入できる必要があります。ベクトルとベクトルの右半分の中央。

注:これは整数除算を使用していること、つまり7/2 = 3であることを理解しています。これは、サイズ7の配列の中央要素のインデックスになります。偶数サイズの配列の場合、上記で実装されたアルゴリズムは、ベクトルの中央にある2つの要素のうち大きい方のインデックス。

とにかく、どんな提案や観察も歓迎され、奨励されています!前もって感謝します。

編集:私が求めているのは、バイナリ検索ツリーのバランスをとる関数をどのように実装するかです。(バランスの取れたBSTは、ノードの数を指定できる最小の深さを持つBSTです。)

4

1 に答える 1

7

平衡二分探索木は、AVL木とも呼ばれます。

このウィキペディアのリンク には、バランスの問題を解決するための良い説明があります。

ツリーのバランスをとる最も簡単な方法は、挿入中です。これは、ヘルパー関数(さまざまなrotateの場合)と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;
};

お役に立てれば!

于 2012-05-08T21:45:50.107 に答える