static void remove_node(struct avl_node **parent, avl_type type, struct addr_mapping *addr) { assert(parent != NULL && *parent != NULL); struct avl_node *node = *parent; struct avl_node *successor; addr_t in_value; addr_t key; in_value = type == P_TO_V ? node->mapping->paddr : node->mapping->vaddr; key = type == P_TO_V ? addr->paddr : addr->vaddr; if ( key == in_value ) { // No Child Case if (node->left == NULL && node->right == NULL) { *parent = NULL; free(node); } // Single Child Cases else if (node->left != NULL && node->right == NULL) { *parent = node->left; free(node); } else if (node->left == NULL && node->right != NULL) { *parent = node->right; free(node); } // Two Children Case else { successor = find_min_node(node->right, type, key); node->mapping->paddr = successor->mapping->paddr; node->mapping->vaddr = successor->mapping->vaddr; remove_node(&(node->right), type, successor->mapping); } // de-allocates and purged from memory return; } if ( key > in_value ) { remove_node(&(node->right), type, addr); avl_update_height(node); avl_balance_node(parent); } else if ( key < in_value ) { remove_node(&(node->left), type, addr); avl_update_height(node); avl_balance_node(parent); } else { printf("Error. Wrongful Traversal. Remove Node Fail\n"); } assert(parent != NULL); }
/** * insert node * * inserts generic node to generic tree * * YOUR RESPONSIBILITY to provide correct tree and correct `key_type` or everything will * F**K UP. * * // parent, pointer to pointer to current node. * // key_type, the key type to use, either P_TO_V or V_TO_P * // child, pointer to the child node. * * CAVEATS: * Assumes that lookup has been performed and confirm that the address has not been mapped. */ static void insert_node(struct avl_node **parent, avl_type key_type, struct avl_node *child) { addr_t child_key, intree_key; if (*parent == NULL) { // Changes the Pointer to the Pointer of the Root Node. *parent = child; } else { struct avl_node *cur = *parent; //printf("Traversing Node Pointer: %p | %p\n", cur, *parent); if (key_type == V_TO_P) { child_key = (addr_t) child->mapping->vaddr; intree_key = (addr_t) cur->mapping->vaddr; } else { child_key = (addr_t) child->mapping->paddr; intree_key = (addr_t) cur->mapping->paddr; } //assumes insertion successful if(child_key < intree_key) { // passes in the pointer to the pointer of the subsequent child node. insert_node(&(cur->left), key_type, child); } else { insert_node(&(cur->right), key_type, child); } avl_update_height(cur); avl_balance_node(parent); } }
/* delete an node from tree */ static avl_node_t* avl_remove_node(avl_node_t* root, avl_key_t key) { int factor = 0; int rotate = 0; if (root == NULL) return NULL; if (key < root->key) { root->left = avl_remove_node(root->left, key); } else if (key > root->key) { root->right = avl_remove_node(root->right, key); } else /* this is the node to be deleted */ { if ((root->left == NULL) || (root->right == NULL)) { avl_node_t* node = (root->left ? root->left : root->right); if (node != NULL) /* one child case */ { *root = *node; } else /* no child case */ { node = root; root = NULL; } avl_free_node(node); } else /* node with two children */ { avl_node_t* node = avl_node_min(root->right); root->key = node->key; root->data = node->data; root->right = avl_remove_node(root->right, node->key); } } if (root == NULL) return NULL; root->height = MAX(HEIGHT(root->left), HEIGHT(root->right)) + 1; factor = avl_get_balance(root); if (factor > 1) { int left_balance = avl_get_balance(root->left); rotate = (left_balance >= 0 ? ROT_LEFT : ROT_RIGHT); } else if (factor < -1) { int right_balance = avl_get_balance(root->right); rotate = (right_balance <= 0 ? ROT_RIGHT : ROT_LEFT); } return avl_balance_node(root, factor, rotate); }
/* insert an node to tree */ static avl_node_t* avl_insert_node(avl_node_t* root, avl_key_t key, void* data) { int rotate = 0; if (root == NULL) { return avl_new_node(key, data); } if (key < root->key) { rotate = ROT_LEFT; root->left = avl_insert_node(root->left, key, data); } else if (key > root->key) { rotate = ROT_RIGHT; root->right = avl_insert_node(root->right, key, data); } else assert(!"duplicated key insertion not supported"); /* update height */ root->height = MAX(HEIGHT(root->left), HEIGHT(root->right)) + 1; return avl_balance_node(root, avl_get_balance(root), rotate); }