2012-05-03 4 views
4

私はbalance_bst(bstNodeルート)関数を作成しようとしていますが、実装には苦労しています。分散バイナリ検索ツリー(BST)のバランスをとるにはどうすればよいですか?

私は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は、ノードの数を指定できる最小の深さを持つものです)。

+0

質問は何ですか? –

+0

申し訳ありませんが、問題は:どのように私はバイナリ検索ツリーのバランスを取るのですか? – MRT89

答えて

7

平衡型バイナリ検索ツリーは、AVLツリー とも呼ばれます。

This wikipedia link には、バランスの問題を解決するための説明があります。

私は、木のバランスをとる最も簡単な方法は挿入中であることを発見しました。ここではヘルパー関数(さまざまな回転のケースのための)と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; 
}; 

・ホープ、このことができます!

+1

OP:AVLコードの正しさを証明することはできませんが、AVLツリーはバイナリツリーのバランスを保証する最も簡単な方法です。他の標準的な方法は赤黒の木であるが、挿入/平衡法はより面倒でエラーが起こりやすい。 – pg1989

+5

"平衡二分探索木はAVLツリーとも呼ばれます。"それは真実ではありません。 AVL樹種は、バランスのとれた樹種の一種であり、別の種は赤黒木である。 –

関連する問題