struct node* insert(struct node* root, int value) { if(root == NULL){ return newnode(value); } if(value < root->data){ root->left = insert(root->left, value); } else { root->right = insert(root->right, value); } root->height = compare(heightof(root->left), heightof(root->right)) + 1; b = balance(root); if(b > 1){ if(value < root->left->data){ //left left return rightrotate(root); } else { //left right root->left = leftrotate(root->left); return rightrotate(root); } } if(b < -1){ if(value > root->right->data){ //right right return leftrotate(root); } else { //right left root->right = rightrotate(root->right); return leftrotate(root); } } return root; }
int balance(struct node* root) { struct node* current = root; if(current == NULL) return 0; return heightof(current->left) - heightof(current->right); }
struct node* rightrotate(struct node *root) { int compare(int, int); struct node *sub = root->left; struct node *b = sub->right; sub->right = root; root->left = b; root->height = compare(heightof(root->left), heightof(root->right)) + 1; sub->height = compare(heightof(sub->left), heightof(sub->right)) + 1; return sub; }
/* check a tree's consistency and balancing */ static void avl_checkheights (struct vm_area_struct * tree) { int h, hl, hr; if (tree == avl_empty) return; avl_checkheights(tree->vm_avl_left); avl_checkheights(tree->vm_avl_right); h = tree->vm_avl_height; hl = heightof(tree->vm_avl_left); hr = heightof(tree->vm_avl_right); if ((h == hl+1) && (hr <= hl) && (hl <= hr+1)) return; if ((h == hr+1) && (hl <= hr) && (hr <= hl+1)) return; printk("%s: avl_checkheights: heights inconsistent\n",avl_check_point); }
/*********************************************************************** * * Method : ut_avlTreeRebalance * Description: * After an insert or remove action this method is called to * rebalance the tree. The insert or remove method will pass the * stack (path to the inserted node). * Implementation : * History : * Algorithm : * 1st : rewind stack and for ech step check tree heights. * 2nd : if heights differ more the 1 then rebalance this level. * Bugs : * ***********************************************************************/ static void ut_avlTreeRebalance ( ut_avlNode **nodeplaces_ptr, os_uint32 count) { for ( ; count > 0 ; count--) { ut_avlNode *nodeplace = *--nodeplaces_ptr; ut_avlNode node = *nodeplace; ut_avlNode nodeleft = node->left; ut_avlNode noderight = node->right; os_uint32 heightleft = heightof(nodeleft); os_uint32 heightright = heightof(noderight); if ((heightright + 1) < heightleft) { ut_avlNode nodeleftleft = nodeleft->left; ut_avlNode nodeleftright = nodeleft->right; os_uint32 heightleftright = heightof(nodeleftright); if (heightof(nodeleftleft) >= heightleftright) { node->left = nodeleftright; nodeleft->right = node; nodeleft->height = 1 + (node->height = 1 + heightleftright); *nodeplace = nodeleft; } else { nodeleft->right = nodeleftright->left; node->left = nodeleftright->right; nodeleftright->left = nodeleft; nodeleftright->right = node; nodeleft->height = node->height = heightleftright; nodeleftright->height = heightleft; *nodeplace = nodeleftright; } } else if ((heightleft + 1) < heightright) { ut_avlNode noderightright = noderight->right; ut_avlNode noderightleft = noderight->left; os_uint32 heightrightleft = heightof(noderightleft); if (heightof(noderightright) >= heightrightleft) { node->right = noderightleft; noderight->left = node; noderight->height = 1 + (node->height = 1 + heightrightleft); *nodeplace = noderight; } else { noderight->left = noderightleft->right; node->right = noderightleft->left; noderightleft->right = noderight; noderightleft->left = node; noderight->height = node->height = heightrightleft; noderightleft->height = heightright; *nodeplace = noderightleft; } } else { os_uint32 height; if (heightleft<heightright) { height = heightright+1; } else { height = heightleft+1; } if (height == node->height) { break; } node->height = height; } } }
/*********************************************************************** * * Method : d_avlTreeRebalance * Description: * After an insert or remove action this method is called to * rebalance the tree. The insert or remove method will pass the * stack (path to the inserted node). * Algorithm : * 1st : rewind stack and for ech step check tree heights. * 2nd : if heights differ more the 1 then rebalance this level. * ***********************************************************************/ static void d_avlTreeRebalance ( d_avlNode ** nodeplaces_ptr, c_long count ) { d_avlNode * nodeplace; d_avlNode node; d_avlNode nodeleft; d_avlNode noderight; c_long heightleft; c_long heightright; d_avlNode nodeleftleft; d_avlNode nodeleftright; c_long heightleftright; d_avlNode noderightright; d_avlNode noderightleft; c_long heightrightleft; c_long height; for ( ; count > 0 ; count--) { nodeplace = *--nodeplaces_ptr; node = *nodeplace; nodeleft = node->left; noderight = node->right; heightleft = heightof(nodeleft); heightright = heightof(noderight); if ((heightright + 1) < heightleft) { nodeleftleft = nodeleft->left; nodeleftright = nodeleft->right; heightleftright = heightof(nodeleftright); if (heightof(nodeleftleft) >= heightleftright) { node->left = nodeleftright; nodeleft->right = node; nodeleft->height = 1 + (node->height = 1 + heightleftright); *nodeplace = nodeleft; } else { nodeleft->right = nodeleftright->left; node->left = nodeleftright->right; nodeleftright->left = nodeleft; nodeleftright->right = node; nodeleft->height = node->height = heightleftright; nodeleftright->height = heightleft; *nodeplace = nodeleftright; } } else if ((heightleft + 1) < heightright) { noderightright = noderight->right; noderightleft = noderight->left; heightrightleft = heightof(noderightleft); if (heightof(noderightright) >= heightrightleft) { node->right = noderightleft; noderight->left = node; noderight->height = 1 + (node->height = 1 + heightrightleft); *nodeplace = noderight; } else { noderight->left = noderightleft->right; node->right = noderightleft->left; noderightleft->right = noderight; noderightleft->left = node; noderight->height = node->height = heightrightleft; noderightleft->height = heightright; *nodeplace = noderightleft; } } else { if (heightleft<heightright) { height = heightright+1; } else { height = heightleft+1; } if (height == node->height) { break; } node->height = height; } } }
static void avl_rebalance (struct vm_area_struct *** nodeplaces_ptr, int count) { for ( ; count > 0 ; count--) { struct vm_area_struct ** nodeplace = *--nodeplaces_ptr; struct vm_area_struct * node = *nodeplace; struct vm_area_struct * nodeleft = node->vm_avl_left; struct vm_area_struct * noderight = node->vm_avl_right; int heightleft = heightof(nodeleft); int heightright = heightof(noderight); if (heightright + 1 < heightleft) { /* */ /* * */ /* / \ */ /* n+2 n */ /* */ struct vm_area_struct * nodeleftleft = nodeleft->vm_avl_left; struct vm_area_struct * nodeleftright = nodeleft->vm_avl_right; int heightleftright = heightof(nodeleftright); if (heightof(nodeleftleft) >= heightleftright) { /* */ /* * n+2|n+3 */ /* / \ / \ */ /* n+2 n --> / n+1|n+2 */ /* / \ | / \ */ /* n+1 n|n+1 n+1 n|n+1 n */ /* */ node->vm_avl_left = nodeleftright; nodeleft->vm_avl_right = node; nodeleft->vm_avl_height = 1 + (node->vm_avl_height = 1 + heightleftright); *nodeplace = nodeleft; } else { /* */ /* * n+2 */ /* / \ / \ */ /* n+2 n --> n+1 n+1 */ /* / \ / \ / \ */ /* n n+1 n L R n */ /* / \ */ /* L R */ /* */ nodeleft->vm_avl_right = nodeleftright->vm_avl_left; node->vm_avl_left = nodeleftright->vm_avl_right; nodeleftright->vm_avl_left = nodeleft; nodeleftright->vm_avl_right = node; nodeleft->vm_avl_height = node->vm_avl_height = heightleftright; nodeleftright->vm_avl_height = heightleft; *nodeplace = nodeleftright; } } else if (heightleft + 1 < heightright) { /* similar to the above, just interchange 'left' <--> 'right' */ struct vm_area_struct * noderightright = noderight->vm_avl_right; struct vm_area_struct * noderightleft = noderight->vm_avl_left; int heightrightleft = heightof(noderightleft); if (heightof(noderightright) >= heightrightleft) { node->vm_avl_right = noderightleft; noderight->vm_avl_left = node; noderight->vm_avl_height = 1 + (node->vm_avl_height = 1 + heightrightleft); *nodeplace = noderight; } else { noderight->vm_avl_left = noderightleft->vm_avl_right; node->vm_avl_right = noderightleft->vm_avl_left; noderightleft->vm_avl_right = noderight; noderightleft->vm_avl_left = node; noderight->vm_avl_height = node->vm_avl_height = heightrightleft; noderightleft->vm_avl_height = heightright; *nodeplace = noderightleft; } } else { int height = (heightleft<heightright ? heightright : heightleft) + 1; if (height == node->vm_avl_height) break; node->vm_avl_height = height; } } }