static caddr_t ravl_delete( Avlnode **root, caddr_t data, IFP fcmp, int *shorter ) { int shortersubtree = 0; int cmp; caddr_t savedata; Avlnode *minnode, *savenode; if ( *root == NULLAVL ) return( 0 ); cmp = (*fcmp)( data, (*root)->avl_data ); /* found it! */ if ( cmp == 0 ) { savenode = *root; savedata = savenode->avl_data; /* simple cases: no left child */ if ( (*root)->avl_left == 0 ) { *root = (*root)->avl_right; *shorter = 1; free( (char *) savenode ); return( savedata ); /* no right child */ } else if ( (*root)->avl_right == 0 ) { *root = (*root)->avl_left; *shorter = 1; free( (char *) savenode ); return( savedata ); } /* * avl_getmin will return to us the smallest node greater * than the one we are trying to delete. deleting this node * from the right subtree is guaranteed to end in one of the * simple cases above. */ minnode = (*root)->avl_right; while ( minnode->avl_left != NULLAVL ) minnode = minnode->avl_left; /* swap the data */ (*root)->avl_data = minnode->avl_data; minnode->avl_data = savedata; savedata = ravl_delete( &(*root)->avl_right, data, fcmp, &shortersubtree ); if ( shortersubtree ) *shorter = right_balance( root ); else *shorter = 0; /* go left */ } else if ( cmp < 0 ) { if ( (savedata = ravl_delete( &(*root)->avl_left, data, fcmp, &shortersubtree )) == 0 ) { *shorter = 0; return( 0 ); } /* left subtree shorter? */ if ( shortersubtree ) *shorter = left_balance( root ); else *shorter = 0; /* go right */ } else { if ( (savedata = ravl_delete( &(*root)->avl_right, data, fcmp, &shortersubtree )) == 0 ) { *shorter = 0; return( 0 ); } if ( shortersubtree ) *shorter = right_balance( root ); else *shorter = 0; } return( savedata ); }
/* * 插入结点到AVL树 * * 结点已存在,返回0;出错,返回-1,成功返回1 */ int insert_avl(struct avl **tree, int item, int *taller) { int ret = 0; if (*tree == NULL) { /* 树为空,插入为根结点 */ *tree = (struct avl *) malloc(sizeof(struct avl)); if (*tree == NULL) return -1; (*tree)->data = item; (*tree)->lchild = (*tree)->rchild = NULL; (*tree)->bf = EH; *taller = 1; /* 树长高了 */ } else { /* 结点已经存在 */ if (item == (*tree)->data) { *taller = 0; return 0; } /* 结点小于根结点,往左子树查找,递归 */ if (item < (*tree)->data) { ret = insert_avl(&(*tree)->lchild, item, taller); if (ret != 1) /* 未插入 */ return ret; /* 新插入结点到左子树,且左子树长高了 */ if (*taller == 1) { /* 检查树的平衡度 */ switch ((*tree)->bf) { case LH: /* 插入结点后,左子树比右子树高,作左平衡处理 */ left_balance(tree); *taller = 0; break; case EH: /* 原本左右子树等高,插入新结点后,根增高 */ (*tree)->bf = LH; *taller = 1; break; case RH: /* 原本右子树比左子树高,插入后等高 */ (*tree)->bf = EH; *taller = 0; break; } } /* 结点大于根结点,往右子树查找,递归 */ } else if (item > (*tree)->data) { ret = insert_avl(&(*tree)->rchild, item, taller); if (ret != 1) /* 未插入 */ return ret; /* 新插入结点到右子树,且右子树长高了 */ if (*taller == 1) { /* 检查树的平衡度 */ switch ((*tree)->bf) { case LH: /* 原本左子树比右子树高,插入后等高 */ (*tree)->bf = EH; *taller = 0; break; case EH: /* 原本左右子树等高,插入结点后,树增高 */ (*tree)->bf = RH; *taller = 1; break; case RH: /* 插入后右子树比左子树高,作右平衡处理 */ right_balance(tree); *taller = 0; break; } } } } return 1; }