anode.cpp

来自「数据结构与程序设计教材源码 数据结构与程序设计教材源码」· C++ 代码 · 共 383 行

CPP
383
字号
 
template <class Record>
AVL_node<Record>::AVL_node()
{
   balance = equal_height;
   left = right = NULL;
}

template <class Record>
AVL_node<Record>::AVL_node(const Record &x)
{
   balance = equal_height;
   left = right = NULL;
   data = x;
}
 
template <class Record>
void AVL_node<Record>::set_balance(Balance_factor b)
{
   balance = b;
}

template <class Record>
Balance_factor AVL_node<Record>::get_balance() const
{
   return balance;
}
 
template <class Record>
Error_code AVL_tree<Record>::avl_insert(Binary_node<Record> *&sub_root,
           const Record &new_data, bool &taller)
 
/* 
 
Pre:  sub_root is either NULL or points to
     a subtree of the AVL_tree
Post: If the key of new_data is already in the subtree, a
      code of duplicate_error is returned.
      Otherwise, a code of success is returned and the Record new_data
      is inserted into the subtree in such a way that the
      properties of an AVL tree have been preserved.
      If the subtree is increased in
      height, the parameter taller is set to
      true; otherwise it is set to false.
Uses: Methods of struct AVL_node; functions avl_insert
      recursively, 
      left_balance, and right_balance.
 
*/

{
   Error_code result = success;
   if (sub_root == NULL) {
      sub_root = new AVL_node<Record>(new_data);
      taller = true;
   }

   else if (new_data == sub_root->data) {
      result = duplicate_error;
      taller = false;
   }

   else if (new_data < sub_root->data) {         //  Insert in left subtree.
      result = avl_insert(sub_root->left, new_data, taller);
      if (taller == true)
         switch (sub_root->get_balance()) {//  Change balance factors.
         case left_higher:
            left_balance(sub_root);
            taller = false;        //  Rebalancing always shortens the tree.
            break;

         case equal_height:
            sub_root->set_balance(left_higher);
            break;

         case right_higher:
            sub_root->set_balance(equal_height);
            taller = false;
            break;
         }
   }

   else {                                       //  Insert in right subtree.
      result = avl_insert(sub_root->right, new_data, taller);
      if (taller == true)
         switch (sub_root->get_balance()) {
         case left_higher:
            sub_root->set_balance(equal_height);
            taller = false;
            break;

         case equal_height:
            sub_root->set_balance(right_higher);
            break;

         case right_higher:
            right_balance(sub_root);
            taller = false;        //  Rebalancing always shortens the tree.
            break;
         }
   }
   return result;
}
 
template <class Record>
void AVL_tree<Record>::right_balance(Binary_node<Record> *&sub_root)
/* 
 
Pre:  sub_root points to a subtree of an AVL_tree that
     is doubly unbalanced on the right.
Post: The AVL properties have been restored to the subtree.
Uses: Methods of struct AVL_node; 
      functions  rotate_right and rotate_left.
 
*/

{
   Binary_node<Record> *&right_tree = sub_root->right;
   switch (right_tree->get_balance()) {
   case right_higher:                            //  single rotation left
      sub_root->set_balance(equal_height);
      right_tree->set_balance(equal_height);
      rotate_left(sub_root);
      break;
 
   case equal_height:  //  impossible case
      cout << "WARNING: program error detected in right_balance" << endl;

   case left_higher:                            //  double rotation left
      Binary_node<Record> *sub_tree = right_tree->left;
      switch (sub_tree->get_balance()) {

      case equal_height:
         sub_root->set_balance(equal_height);
         right_tree->set_balance(equal_height);
         break;

      case left_higher:
         sub_root->set_balance(equal_height);
         right_tree->set_balance(right_higher);
         break;

      case right_higher:
         sub_root->set_balance(left_higher);
         right_tree->set_balance(equal_height);
         break;
      }

      sub_tree->set_balance(equal_height);
      rotate_right(right_tree);
      rotate_left(sub_root);
      break;
   }
}
 
template <class Record>
void AVL_tree<Record>::left_balance(Binary_node<Record> *&sub_root)
{
   Binary_node<Record> *&left_tree = sub_root->left;
   switch (left_tree->get_balance()) {
   case left_higher:
      sub_root->set_balance(equal_height);
      left_tree->set_balance(equal_height);
      rotate_right(sub_root);
      break;

   case equal_height:  //  impossible case
      cout << "WARNING: program error detected in left_balance" << endl;

   case right_higher:
      Binary_node<Record> *sub_tree = left_tree->right;
      switch (sub_tree->get_balance()) {

      case equal_height:
         sub_root->set_balance(equal_height);
         left_tree->set_balance(equal_height);
         break;

      case right_higher:
         sub_root->set_balance(equal_height);
         left_tree->set_balance(left_higher);
         break;

      case left_higher:
         sub_root->set_balance(right_higher);
         left_tree->set_balance(equal_height);
         break;
      }

      sub_tree->set_balance(equal_height);
      rotate_left(left_tree);
      rotate_right(sub_root);
      break;
   }
}
 
template <class Record>
void AVL_tree<Record>::rotate_left(Binary_node<Record> *&sub_root)
/* 
 
Pre:  sub_root points to a subtree of the AVL_tree.
      This subtree has a nonempty right subtree.
Post: sub_root is reset to point to its former right child, and the former
      sub_root node is the left child of the new sub_root node.
 
*/

{
   if (sub_root == NULL || sub_root->right == NULL)     //  impossible cases
      cout << "WARNING: program error detected in rotate_left" << endl;
   else {
      Binary_node<Record> *right_tree = sub_root->right;
      sub_root->right = right_tree->left;
      right_tree->left = sub_root;
      sub_root = right_tree;
   }
}
 
template <class Record>
void AVL_tree<Record>::rotate_right(Binary_node<Record> *&sub_root)
{
   if (sub_root == NULL || sub_root->left == NULL) //  impossible cases
      cout << "WARNING: program error in detected in rotate_right" << endl;
   else {
      Binary_node<Record> *left_tree = sub_root->left;
      sub_root->left = left_tree->right;
      left_tree->right = sub_root;
      sub_root = left_tree;
   }
}
 
template <class Record>
Error_code AVL_tree<Record>::remove_avl(Binary_node<Record> *&sub_root,
           const Record &target, bool &shorter)
 
{
   Binary_node<Record> *temp;
   if (sub_root == NULL) return fail;
   else if (target < sub_root->data)
      return remove_avl_left(sub_root, target, shorter);
   else if (target > sub_root->data)
      return remove_avl_right(sub_root, target, shorter);

   else if (sub_root->left == NULL) { //  Found the target: delete current node.
      temp = sub_root;                //  Move right subtree up to delete node.
      sub_root = sub_root->right;
      delete temp;
      shorter = true;
   }

   else if (sub_root->right == NULL) {
      temp = sub_root;                //  Move left subtree up to delete node.
      sub_root = sub_root->left;
      delete temp;
      shorter = true;
   }

   else if (sub_root->get_balance() == left_higher) { //  Neither subtree is empty; delete from the taller.
      temp = sub_root->left;                     //  Find predecessor of target and delete it from left tree.
      while (temp->right != NULL) temp = temp->right;
      sub_root->data = temp->data;
      remove_avl_left(sub_root, temp->data, shorter);
   }

   else {                                   //  Find successor of target and delete from right.
      temp = sub_root->right;
      while (temp->left != NULL) temp = temp->left;
      sub_root->data = temp->data;
      remove_avl_right(sub_root, temp->data, shorter);
   }
   return success;
}
 
template <class Record>
Error_code AVL_tree<Record>::remove_avl_right(Binary_node<Record> *&sub_root,
           const Record &target, bool &shorter)
 
{
   Error_code result = remove_avl(sub_root->right, target, shorter);
   if (shorter == true) switch (sub_root->get_balance()) {
   case equal_height:                      //  case 1 in text
      sub_root->set_balance(left_higher);
      shorter = false;
      break;

   case right_higher:                      //  case 2 in text
      sub_root->set_balance(equal_height);
      break;

   case left_higher:  //  case 3 in text: shortened shorter subtree; must rotate
      Binary_node<Record> *temp = sub_root->left;
      switch (temp->get_balance()) {
      case equal_height:       //  case 3a
         temp->set_balance(right_higher);
         rotate_right(sub_root);
         shorter = false;
         break;

      case left_higher:       //  case 3b
         sub_root->set_balance(equal_height);
         temp->set_balance(equal_height);
         rotate_right(sub_root);
         break;

      case right_higher:        //  case 3c; requires double rotation
         Binary_node<Record> *temp_right = temp->right;
         switch (temp_right->get_balance()) {
         case equal_height:
            sub_root->set_balance(equal_height);
            temp->set_balance(equal_height);
            break;
         case left_higher:
            sub_root->set_balance(right_higher);
            temp->set_balance(equal_height);
            break;
         case right_higher:
            sub_root->set_balance(equal_height);
            temp->set_balance(left_higher);
            break;
         }
         temp_right->set_balance(equal_height);
         rotate_left(sub_root->left);
         rotate_right(sub_root);
         break;
      }
   }
   return result;
}
 
template <class Record>
Error_code AVL_tree<Record>::remove_avl_left(Binary_node<Record> *&sub_root,
           const Record &target, bool &shorter)
 
{
   Error_code result = remove_avl(sub_root->left, target, shorter);
   if (shorter == true) switch (sub_root->get_balance()) {
   case equal_height:                      //  case 1 in text
      sub_root->set_balance(right_higher);
      shorter = false;
      break;

   case left_higher:                      //  case 2 in text
      sub_root->set_balance(equal_height);
      break;

   case right_higher:  //  case 3 in text: shortened shorter subtree; must rotate
      Binary_node<Record> *temp = sub_root->right;
      switch (temp->get_balance()) {
      case equal_height:       //  case 3a
         temp->set_balance(left_higher);
         rotate_left(sub_root);
         shorter = false;
         break;
      case right_higher:       //  case 3b
         sub_root->set_balance(equal_height);
         temp->set_balance(equal_height);
         rotate_left(sub_root);
         break;
      case left_higher:        //  case 3c; requires double rotation
         Binary_node<Record> *temp_left = temp->left;
         switch (temp_left->get_balance()) {
         case equal_height:
            sub_root->set_balance(equal_height);
            temp->set_balance(equal_height);
            break;
         case right_higher:
            sub_root->set_balance(left_higher);
            temp->set_balance(equal_height);
            break;
         case left_higher:
            sub_root->set_balance(equal_height);
            temp->set_balance(right_higher);
            break;
         }
         temp_left->set_balance(equal_height);
         rotate_right(sub_root->right);
         rotate_left(sub_root);
         break;
      }
   }
   return result;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?