Beispiel #1
0
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;
}