|
struct Node; typedef Node* Tree; typedef const Node* ConstTree; int height(ConstTree T); struct Node { int item; // Information at this node int ht; // height of this node Node* left; // The left subtree Node* right; // The right subtree Node(int it, Node* lft, Node* rgt) { item = it; left = lft; right = rgt; ht = 1 + max(height(lft), height(rgt)); } }; //========================================== // height //========================================== // height(T) returns the height of tree T. // // Requirement: If T is nonempty, then the // ht field has already been set correctly // T. //========================================== int height(ConstTree T) { if(T == NULL) { return 0; } else { return T->ht; } } //========================================== // installHeight //========================================== // installHeight(T) sets T->ht to the // height of T. // // Requirements: // (1) T is not empty. // (2) The ht field has already been set // correctly in every node of each // subtree of T. //========================================== void installHeight(Tree T) { T->ht = 1 + max(height(T->left), height(T->right)); }
//========================================== // singleRotateLeft //========================================== // singleRotateLeft(T) performs a single // rotation from right to left at the // root of T. //========================================== void singleRotateLeft(Tree& T) { Tree r = T->right; T->right = r->left; installHeight(T); r->left = T; T = r; installHeight(T); } //========================================== // singleRotateRight //========================================== // singleRotateRight(T) performs a single // rotation from left to right at the // root of T. //========================================== void singleRotateRight(Tree& T) { Tree L = T->left; T->left = L->right; installHeight(T); L->right = T; T = L; installHeight(T); } //========================================== // doubleRotateLeft //========================================== // doubleRotateLeft(T) performs a double // rotation from right to left at the // root of T. //========================================== void doubleRotateLeft(Tree& T) { singleRotateRight(T->right); singleRotateLeft(T); } //========================================== // doubleRotateRight //========================================== // doubleRotateRight(T) performs a double // rotation from left to right at the // root of T. //========================================== void doubleRotateRight(Tree& T) { singleRotateLeft(T->left); singleRotateRight(T); } //========================================== // rotateLeft //========================================== // rotateLeft(T) performs a rotation from // from right to left at the root of T, // choosing a single or double rotation. //========================================== void rotateLeft(Tree& T) { Tree r = T->right; int zag = height(r->left); int zig = height(r->right); if(zig > zag) { singleRotateLeft(T); } else { doubleRotateLeft(T); } } //========================================== // rotateRight //========================================== // rotateRight(T) performs a rotation from // from left to right at the root of T, // choosing a single or double rotation. //========================================== void rotateRight(Tree& T) { Tree L = T->left; int zig = height(L->left); int zag = height(L->right); if(zig > zag) { singleRotateRight(T); } else { doubleRotateRight(T); } } //========================================== // rebalance //========================================== // rebalance(T) does the following. // // (1) Perform a rotation at T if required. // // (2) Set the ht field of T correctly, // regardless of whether or not a // rotation is done. // // Requirement: T must not be empty. //========================================== void rebalance(Tree& T) { int hl = height(T->left); int hr = height(T->right); if(hr > hl + 1) { rotateLeft(T); } else if(hl > hr + 1) { rotateRight(T); } else { installHeight(T); } }
Inserting with rebalancing is just the basic algorithm, but with a call to rebalance each time a subtree of a node is modified.
//================================================= // insert //================================================= // insert(x,T) inserts x into binary search tree T. // If x is already a member of T, it does nothing. // // This function rebalances T after the insertion // if necessary. It requires that T is // height-balanced when insert is called. //================================================= void insert(const int x, Tree& T) { if(T == NULL) { T = new Node(x, NULL, NULL); } else if(x < T->item) { insert(x, T->left); rebalance(T); } else if(x > T->item) { insert(x, T->right); rebalance(T); } }
For removeSmallest and remove, start with the basic functions, but rebalance any time a subtree of a node is modified.
//==================================================== // removeSmallest //==================================================== // removeSmallest(T) removes the smallest value from // binary search tree T and returns the value that // was removed. // // Requirement: T must not be an empty tree. // // This function rebalances T after removing the // smallest value, if necessary. It requires that T // is height-balanced when removeSmallest is called. //==================================================== int removeSmallest(Tree& T) { if(T->left == NULL) { int result = T->item; Tree p = T; T = T->right; // subtrees are already balanced. delete p; return result; } else { int result = removeSmallest(T->left); rebalance(T); return result; } } //==================================================== // remove //==================================================== // remove(x,T) removes x from binary search tree T. // If x is not in T, it does nothing. // // This function rebalances T after removing x, // if necessary. It requires that T is height-balanced // when remove is called. //==================================================== void remove(const int x, Tree& T) { if(T != NULL) { if(x < T->item) { remove(x, T->left); rebalance(T); } else if(x > T->item) { remove(x, T->right); rebalance(T); } else if(T->left == NULL) { Tree p = T; T = T->right; delete p; } else if(T->right == NULL) { Tree p = T; T = T->left; delete p; } else { T->item = removeSmallest(T->right); rebalance(T); } } }
Lookup is the same as for an unbalanced tree.
|