base_bnt.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 482 行 · 第 1/2 页

C
482
字号
        ptr->ltree = raised_node;               //  change ltree to raised node
      else if (route == RIGHT)                  // or for right route
        ptr->rtree = raised_node;               //  change rtree to raised node
      raised_node = NULL;
    }
    if (more_todo == FALSE)                     // Exit loop when all balanced
      break;
    
    if (route == LEFT) {                        // Node inserted as an LTREE
      switch (ptr->avl_balance) {               // Depending on node's balance
      case 1:
        ptr->avl_balance = 0;                   // Set node as balanced
        more_todo = FALSE;
        break;
      case 0:
        ptr->avl_balance = -1;                  // Set node as 1 heavy on left
        break;
      case -1:                                  // Will need to rotate
        more_todo = FALSE;
        p1 = ptr->ltree;                        
        if (p1->avl_balance == -1) {            // Single Right Rotation
          ptr->ltree = p1->rtree;
          p1->rtree = ptr;
          p1->avl_balance = 0;
          ptr->avl_balance = 0;
          raised_node = p1;                     // This node bubbled up
        }                                       // End Single right rotation
        else {                                  // Double Right Rotation
          p2 = p1->rtree;
          p1->rtree = p2->ltree;
          p2->ltree = p1;
          ptr->ltree = p2->rtree;
          p2->rtree = ptr;
          if (p2->avl_balance == -1)            // update balance for ptr
            ptr->avl_balance = 1;
          else
            ptr->avl_balance = 0;
          if (p2->avl_balance == 1)             // update balance for p1
            p1->avl_balance = -1;
          else
            p1->avl_balance = 0;
          p2->avl_balance = 0;                  // update balance for p2
          raised_node = p2;                     // This node now moved up
          break;
        }                                       // End Left Right Rotation
      }                                         // End switch
    }                                           // End LTREE path
    
    else {                                      // Node inserted as an RTREE
      switch (ptr->avl_balance) {
      case -1:
        ptr->avl_balance = 0;                   // Node is now balanced
        more_todo = FALSE;                      // Tree is now balanced
        break;
      case 0:
        ptr->avl_balance = 1;                   // Node is 1 heavy on right
        break;
      case 1:                                   // Will need to rotate
        more_todo = FALSE;
        p1 = ptr->rtree;
        if (p1->avl_balance == 1) {             // Single Left Rotation
          ptr->rtree = p1->ltree;
          p1->ltree = ptr;
          p1->avl_balance = 0;
          ptr->avl_balance = 0;
          raised_node = p1;
        }                                       // End Single Left Rotation
        else {                                  // Right/Left Rotation
          p2 = p1->ltree;
          p1->ltree = p2->rtree;
          p2->rtree = p1;
          ptr->rtree = p2->ltree;
          p2->ltree = ptr;
          if (p2->avl_balance == 1)             // Update balance for ptr
            ptr->avl_balance = -1;
          else
            ptr->avl_balance = 0;
          if (p2->avl_balance == -1)            // Update balance for p1
            p1->avl_balance = 1;
          else
            p1->avl_balance = 0;
          p2->avl_balance = 0;                  // update balance for p2
          raised_node = p2;                     // This node now moved up
          break;
        }                                       // End Right/Left Rotation
      }                                         // End switch
    }                                           // End RTREE path
  }

  if (raised_node != NULL) {                    // When a node gets raised
    this->root = raised_node;                   //  raised_node to be root
  }
}

// Balances the nodes in the path of a removed node for an AVL Binary Tree
// The parent nodes and index to their subtrees are maintained in a Stack of 
// Stack_entrys
 
void CoolBase_Binary_Tree::avl_remove_balance (BT_Stack &stack) {
  CoolBase_Binary_Node *p, *p1, *p2, *raised_node=NULL; // Temporary pointers to nodes
  Boolean more_todo=TRUE;                       // When more_todo is FALSE, done.
  Left_Right route=NONE;
  while (stack.length() > 0) {                  // Loop thru nodes on stack
    Stack_Entry stack_entry = stack.pop();      // Get next stack_entry
    p = stack_entry.get_first();                // Get Node 
    route = (Left_Right)stack_entry.get_second();// Get the subtree

    // UPDATE PARENT TO POINT AT RAISED NODE FROM PREVIOUS ITERATION
    if (raised_node != NULL) {                  // If there is a raised node
      if (route == LEFT)                        //    See what side was changed
          p->ltree = raised_node;               //    Update ltree
      else
        p->rtree = raised_node;                 //    or update rtree
      raised_node = NULL;                       //    raised_node taken care of.
    }

    if (more_todo == FALSE)                     // Tree is balanced
      break;

    // BALANCE LEFT SUBTREE OF NODE P.  Note that this is VERY similar 
    // to the code below to balance the right side.  Changes here are likely
    // necessary below also.

    if (route == LEFT) {
      switch (p->avl_balance) {
      case -1:                                  // Set balance to 0. 
        p->avl_balance = 0;                     //   balance parent node
        break;
      case 0:                                   // Set balance to 1.  Tree is 
        p->avl_balance = 1;                     //   all balanced.
        more_todo = FALSE;
        break;
      case 1:                                   // Need to rotate
        p1 = p->rtree;
        if (p1->avl_balance >= 0) {             
          p->rtree = p1->ltree;                 // Single left rotate
          p1->ltree = p;
          raised_node = p1;
          if (p1->avl_balance == 0) {           // Update p and p1 balance
            p->avl_balance = 1;
            p1->avl_balance = -1;
            more_todo = FALSE;
          }
          else {
            p->avl_balance = 0;
            p1->avl_balance = 0;
          }
        }
        else {                                  // Double right left rotate
          p2 = p1->ltree;
          p1->ltree = p2->rtree;
          p2->rtree = p1;
          p->rtree = p2->ltree;
          p2->ltree = p;
          int b2 = p2->avl_balance;
          if (b2 == 1)                          // Set new balance for node p
            p->avl_balance = -1;
          else
            p->avl_balance = 0;
          if (b2 == -1)                         // Set new balance for node p1
            p1->avl_balance = 1;
          else 
            p1->avl_balance = 0;

          p2->avl_balance = 0;                  // Set new balance for node p2
          raised_node = p2;             
        }
      }
    }
    // BALANCE RIGHT SUBTREE OF NODE P.  Note that this is VERY similar
    // to the code above to balance the left side.  Changes here are likely
    // necessary above also.
    else {
      switch (p->avl_balance) {
      case 1:                                   // Set balance to 0. 
        p->avl_balance = 0;                     //   balance parent node
        break;
      case 0:                                   // Set balance to 1.  Tree is 
        p->avl_balance = -1;                    //   all balanced.
        more_todo = FALSE;
        break;
      case -1:                                  // Need to rotate
        p1 = p->ltree;
        if (p1->avl_balance <= 0) {             // Single right rotate
          p->ltree = p1->rtree;
          p1->rtree = p;
          raised_node = p1;
          if (p1->avl_balance == 0) {           // Update p and p1 balance
            p->avl_balance = -1;
            p1->avl_balance = 1;
            more_todo = FALSE;                  
          }
          else {
            p->avl_balance = 0;
            p1->avl_balance = 0;
          }
        }
        else {                                  // Double left right rotate
          p2 = p1->rtree;
          p1->rtree = p2->ltree;
          p2->ltree = p1;
          p->ltree = p2->rtree;
          p2->rtree = p;
          int b2 = p2->avl_balance;
          if (b2 == -1)                         // Set new balance for node p
            p->avl_balance = 1;
          else
            p->avl_balance = 0;
          if (b2 == 1)                          // Set new balance for node p1
            p1->avl_balance = -1;
          else
            p1->avl_balance = 0;

          p2->avl_balance = 0;                  // Set new balance for node p2
          raised_node = p2;
        }
      }
    }
  }

  // If raised_node is non_null, after all the balancing is done, it means
  // we have a new root. 
  if (raised_node != NULL) {
    this->root = raised_node;
  }
}
                          

// curpos_error -- Raise exception for invalid current position
// Input:         Character string of function and type
// Output:        None

void CoolBase_Binary_Tree::curpos_error (const char* Type, const char* fcn) {
  //RAISE Error, SYM(CoolBase_Binary_Tree), SYM(Invalid_Cpos),
  printf ("CoolBase_Binary_Tree<%s>::%s: Invalid current position.\n", Type, fcn);
  abort ();
}



⌨️ 快捷键说明

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