// If node X is a leaf or has only one child, skip to step 5. (node Z will be node X) // Otherwise, determine node Y by finding the largest node in node X's left sub tree (in-order predecessor) or the smallest in its right sub tree (in-order successor). // Replace node X with node Y (remember, tree structure doesn't change here, only the values). In this step, node X is essentially deleted when its internal values were overwritten with node Y's. // Choose node Z to be the old node Y. // Attach node Z's subtree to its parent (if it has a subtree). If node Z's parent is null, update root. (node Z is currently root) // Delete node Z. // Retrace the path back up the tree (starting with node Z's parent) to the root, adjusting the balance factors as needed. // As with all binary trees, a node's in-order successor is the left-most child of its right subtree, and a node's in-order predecessor is the right-most child of its left subtree. // In either case, this node will have zero or one children. Delete it according to one of the two simpler cases above. // Removes one element from the dictionary bool AVLDictionary::removeElement(KeyType key) { if (debug) { printf("------------------------------------\n"); printf("removeElement(\"%s\")\n", key); printf("---------- Before -----------------\n"); printNode("", root, 0); } //need to subsitute root with node that comes immediately before or after // AVLNode *current = (AVLNode*)findNode(key); AVLNode *current = root; while (current != NULL) { if (strcmp(current->key, key) == 0) { break; } else if (strcmp(current->key, key) > 0) { current = current->left; } else { current = current->right; } } if (current == NULL) { return false; } AVLNode *parent = NULL; if (current != root) { parent = current->parent; } else { //is root current->left = current->right->parent; } // if(current == parent->right) { // parent->right = current->right; // } else { // parent->left = current->right; // } if (current->left == NULL && current->right == NULL) { //no children, just delete? if (current == parent->right) { parent->right = NULL; } else { parent->left = NULL; } delete current; restructure(parent); } else if (current->left == NULL) { if (current == parent->right) { parent->right = NULL; parent->right = current->right; parent->right->height = current->right->height; delete current; current = NULL; restructure(parent); } else { parent->left = NULL; parent->left = current->right; parent->left->height = current->right->height; restructure(parent); delete current; current = NULL; } // restructure(current->right); } else if (current->right == NULL) { if (current == parent->right) { parent->right = NULL; parent->right = current->left; parent->right->height = current->left->height; // current = current->right; restructure(parent); delete current; current = NULL; } else { parent->left = NULL; parent->left = current->left; parent->left->height = current->left->height; restructure(parent); delete current; current = NULL; // current = current->right; } // delete current; // restructure(parent); // parent->left = current->right; // current = current->right; // restructure(current); // restructure(current->left); } else { //is internal AVLNode *preorder = current->left; while (preorder->right != NULL) { preorder = preorder->right; } current->key = preorder->key; current->data = preorder->data; current = preorder; if (current->left == NULL) { if (current->parent->right == current) { current->parent->right = current->right; } else { current->parent->left = current->right; } } else { if (current->parent->right == current) { current->parent->right = current->left; } else { current->parent->left = current->left; } } restructure(current->parent); delete current; } if (debug) { printf("---------- After -----------------\n"); printNode("", root, 0); checkRecursive(root); } return true; }
// Add a record to the dictionary. Returns false if key already exists bool AVLDictionary::addRecord( KeyType key, DataType data) { if ( debug) { printf("------------------------------------\n"); printf("addRecord(\"%s\",%d)\n", key, (int)data); printf("---------- Before -----------------\n"); printNode("", root, 0); } //find node with that key, if any //overwrite data if found AVLNode *current = root; AVLNode *prev = NULL; while (current != NULL) { prev = current; if (strcmp(key, current->key) == 0) { // key == current->key) // //found, overwrite data current->data = data; return false; } else if (strcmp(key, current->key) > 0) { // (key - current->key > 0) //key is in right subtree current = current->right; } else { //key is in left subtree current = current->left; } } //did not find key in tree, and prev points to parent node where new node will be inserted AVLNode *newNode = new AVLNode(); newNode->key = strdup(key); //use strdup if key is const char* newNode->data = data; newNode->height = 1; newNode->left = NULL; newNode->right = NULL; newNode->parent = prev; if (prev == NULL) { //tree is empty, assign to root root = newNode; nElements++; return true; } if (strcmp(key, prev->key) > 0) { //attach to right prev->right = newNode; } else { prev->left = newNode; } //adjust heights of above subtrees, path from inserted node to root AVLNode *m = newNode->parent; while (m != NULL) {//go up //get maxHeight of left and right children int maxHeight = 0; if (m->left != NULL) { maxHeight = m->left->height; } if (m->right != NULL && maxHeight < m->right->height) { maxHeight = m->right->height; } //update height of m m->height = 1 + maxHeight; m = m->parent; } //at this point, the newnode is in place and height has been adjusted for correctness, //however, may not fulfill AVL tree conditions, because of potential height differences //in subtrees (ie difference in height of left and right > 1) //restructure beginning at inserted node //Find node to insert into //Node does not exist. Create it. //Height might not be valid anymore. //We need to restructure . if ( debug) { printf("---------- Before Restructure -----------------\n"); printNode("", root, 0); } // Call restructure restructure(newNode); if (debug) { checkRecursive(root); printf("---------- After Restructure -----------------\n"); printNode("", root, 0); } nElements++; return true; }
void AVLDictionary::checkRecursive(AVLNode * node) { if (node == NULL) { return; } if (node->left!=NULL) { // Make sure that it is sorted if ( strcmp(node->key, node->left->key) <= 0) { fprintf(stderr, "*** NOT SORTED: parent->key=\"%s\" <= left->key=\"%s\"\n", node->key, node->left->key); assert(0); } } if (node->right!=NULL) { // Make sure that it is sorted if ( strcmp(node->key, node->right->key) >= 0) { fprintf(stderr, "*** NOT SORTED: parent->key=\"%s\" >= right->key=\"%s\"\n", node->key, node->right->key); assert(0); } } checkRecursive(node->left); checkRecursive(node->right); // Check height int lHeight = 0; if (node->left!=0) { lHeight = node->left->height; } int rHeight = 0; if (node->right!=0) { rHeight = node->right->height; } int diff = lHeight - rHeight; if (diff<0) { diff = - diff; } if (diff>1) { fprintf(stderr, "*** HEIGHT DIFFERENCE > 1: key=\"%s\" lheight=%d rheight=%d\n", node->key, lHeight, rHeight); assert(0); } // Compute height int maxHeight = lHeight; if (maxHeight<rHeight) { maxHeight = rHeight; } if (node->height != maxHeight + 1) { fprintf(stderr, "*** WRONGH HEIGHT: key=\"%s\" height=%d should be %d\n", node->key, node->height, maxHeight + 1); assert(0); } }
// // Goes over the nodes in the tree to verify that the height and keys // of the AVL tree are correct. It prints a message and exits if it is not a // valid AVL tree. // void AVLDictionary::check() { checkRecursive(root); }
// Removes one element from the dictionary bool AVLDictionary::removeElement(KeyType key) { if (debug) { printf("------------------------------------\n"); printf("removeElement(\"%s\")\n", key); printf("---------- Before -----------------\n"); printNode("", root, 0); } AVLNode *node; node = findNode(key); if (node == NULL) { return false; } if (node->left == NULL && node->right == NULL) { if ( node == node->parent->left) { node->parent->left = NULL; } else { node->parent->right = NULL; } AVLNode *m; m = node->parent; while(m != NULL) { int maxheight = 0; if(m->left != NULL) { maxheight = m->left->height; } if (m->right != NULL && maxheight < m->right->height) { maxheight = m->right->height; } m->height = maxheight +1; m = m->parent; } restructure(node->parent); delete node; } else if (node->left == NULL) { AVLNode temp; temp.height = node->height; strcpy((char*)temp.key, node->key); temp.data = node->data; node->height = node->right->height; strcpy((char*)node->key, node->right->key); node->data = node->right->data; node->right->height = temp.height; strcpy((char*)node->right->key, temp.key); node->right->data = temp.data; delete node->right; node->right = NULL; AVLNode *m = node->parent; while(m != NULL) { int maxheight = 0; if(m->left != NULL) { maxheight = m->left->height; } if (m->right != NULL && maxheight < m->right->height) { maxheight = m->right->height; } m->height = maxheight +1; m = m->parent; } restructure(node); } else if (node->right == NULL) { AVLNode temp; temp.height = node->height; strcpy((char*)temp.key, node->key); temp.data = node->data; node->height = node->left->height; strcpy((char*)node->key, node->left->key); node->data = node->left->data; node->left->height = temp.height; strcpy((char*)node->left->key, temp.key); node->left->data = temp.data; delete node->left; node->left = NULL; AVLNode *m; m = node->parent; while(m != NULL) { int maxheight = 0; if( m->left != NULL) { maxheight = m->left->height; } if (m->right != NULL && maxheight < m->right->height) { maxheight = m->right->height; } m->height = maxheight +1; m = m->parent; } restructure(node); } else { AVLNode *replacement; replacement = node->left; if (replacement->right == NULL) { replacement = node->right; while(replacement->left != NULL) { replacement = replacement->left; } } else { while (replacement->right != NULL) { replacement = replacement->right; } } AVLNode temp; temp.height = node->height; strcpy((char*)temp.key, node->key); temp.data = node->data; node->height = replacement->height; strcpy((char*)node->key, replacement->key); node->data = replacement->data; replacement->height = temp.height; strcpy((char*)replacement->key, temp.key); replacement->data = temp.data; AVLNode *n; n = replacement->parent; if (n != NULL) { if (replacement == n->left) { n->left = NULL; delete replacement; } else { n->right = NULL; delete replacement; } AVLNode *m = n; while(m != NULL) { int maxheight = 0; if(m->left != NULL) { maxheight = m->left->height; } if (m->right != NULL && maxheight < m->right->height) { maxheight = m->right->height; } m->height = maxheight +1; m = m->parent; } restructure(n); } } nElements--; if (debug) { printf("---------- After -----------------\n"); printNode("", root, 0); checkRecursive(root); } return true; }
// Add a record to the dictionary. Returns false if key already exists bool AVLDictionary::addRecord( KeyType key, DataType record) { if (debug) { printf("------------------------------------\n"); printf("addRecord(\"%s\",%d)\n", key, record); printf("---------- Before -----------------\n"); printNode("", root, 0); } AVLNode *n; n = new AVLNode(); n->key = key; n->data = record; n->height = 1; n->left = NULL; n->right = NULL; n->parent = NULL; if(root == NULL) { root = n; nElements++; return true; } AVLNode *curr; curr = root; AVLNode *prev; prev = NULL; while(curr != NULL) { prev = curr; if (strcmp(key, curr->key) < 0) { curr = curr->left; } else if (strcmp(key, curr->key) > 0) { curr = curr->right; } else { curr->data = record; return false; } } if (strcmp(key, prev->key) < 0) { prev->left = n; } else { prev->right = n; } n->parent = prev; AVLNode *m; m = n->parent; while(m != NULL) { int maxheight = 0; if(m->left != NULL) maxheight = m->left->height; if(m->right != NULL && maxheight < m->right->height) maxheight = m->right->height; m->height = 1+maxheight; m = m->parent; } if (debug) { printf("---------- Before Restructure -----------------\n"); printNode("", root, 0); } restructure(n); if (debug) { checkRecursive(root); printf("---------- After Restructure -----------------\n"); printNode("", root, 0); } nElements++; return true; }