我正在研究AVL树,似乎无法找到关于删除的参考代码(通过谷歌搜索或我方便的几本教科书)。
我不知道为什么会这样,但你知道在java中删除AVL的任何参考/例子吗?
(我只发现了这个:avl tree removal它在链接中声明它在测试中失败了)
答案 0 :(得分:3)
我有一个AVL Tree in Java的实现,如果你想用它来参考,它已经过很好的测试。它基于维基百科的描述,并且评论很好。
就像在常规BST插入后必须保持平衡一样。您可以像BST一样删除节点,然后根据以下算法进行平衡。
BST删除后的平衡情况是(节点是用于替换已删除节点的节点的父节点):
... remove code ...
// Re-balance the tree all the way up the tree
while (nodeToRefactor != null) {
nodeToRefactor.updateHeight();
balanceAfterDelete(nodeToRefactor);
nodeToRefactor = (AVLNode<T>) nodeToRefactor.parent;
}
... remove code ...
... balance code ...
int balanceFactor = node.getBalanceFactor();
if (balanceFactor==-2 || balanceFactor==2) {
if (balanceFactor==-2) {
AVLNode<T> ll = (AVLNode<T>) node.lesser.lesser;
int lesser = ll.height;
AVLNode<T> lr = (AVLNode<T>) node.lesser.greater;
int greater = lr.height;
if (lesser>=greater) {
rightRotation(node);
} else {
leftRotation(node.lesser);
rightRotation(node);
}
} else if (balanceFactor==2) {
AVLNode<T> rr = (AVLNode<T>) node.greater.greater;
int greater = rr.height;
AVLNode<T> rl = (AVLNode<T>) node.greater.lesser;
int lesser = rl.height;
if (greater>=lesser) {
leftRotation(node);
} else {
rightRotation(node.greater);
leftRotation(node);
}
}
}
答案 1 :(得分:2)
一旦你实现了balance()
......
首先想到的是在Apache Commons Collections中实现TreeList,它是一个由AVL树支持的列表。 http://www.docjar.org/html/api/org/apache/commons/collections/list/TreeList.java.html有源代码。
答案 2 :(得分:2)
树删除的工作原理是搜索(以与查找相同的方式),直到找到要删除的节点,用最小的后继者替换它(你也可以使用它的最大前导),然后重新平衡树。重新平衡是自下而上的;在找到要删除的节点之后,算法将向下插入右子树的左侧脊柱,找到最小的后继,并重新平衡,因为它以树的形式返回到被删除的节点,由最小的后继节点替换。当树中不存在被删除的项时,会发生唯一的特殊情况,在这种情况下,树将保持不变。 Here是我在Scheme中实现的AVL树;通过使用递归而不是更传统的迭代,代码变得非常简单:
(define (tree k v l r)
(vector k v l r (+ (max (ht l) (ht r)) 1)))
(define (key t) (vector-ref t 0))
(define (val t) (vector-ref t 1))
(define (lkid t) (vector-ref t 2))
(define (rkid t) (vector-ref t 3))
(define (ht t) (vector-ref t 4))
(define (bal t) (- (ht (lkid t)) (ht (rkid t))))
(define nil (vector 'nil 'nil 'nil 'nil 0))
(vector-set! nil 2 nil)
(vector-set! nil 3 nil)
(define (nil? t) (eq? t nil))
(define (rot-left t)
(if (nil? t) t
(tree (key (rkid t))
(val (rkid t))
(tree (key t) (val t) (lkid t) (lkid (rkid t)))
(rkid (rkid t)))))
(define (rot-right t)
(if (nil? t) t
(tree (key (lkid t))
(val (lkid t))
(lkid (lkid t))
(tree (key t) (val t) (rkid (lkid t)) (rkid t)))))
(define (balance t)
(let ((b (bal t)))
(cond ((< (abs b) 2) t)
((positive? b)
(if (< -1 (bal (lkid t))) (rot-right t)
(rot-right (tree (key t) (val t)
(rot-left (lkid t)) (rkid t)))))
((negative? b)
(if (< (bal (rkid t)) 1) (rot-left t)
(rot-left (tree (key t) (val t)
(lkid t) (rot-right (rkid t)))))))))
(define (lookup lt? t k)
(cond ((nil? t) #f)
((lt? k (key t)) (lookup lt? (lkid t) k))
((lt? (key t) k) (lookup lt? (rkid t) k))
(else (cons k (val t)))))
(define (insert lt? t k v)
(cond ((nil? t) (tree k v nil nil))
((lt? k (key t))
(balance (tree (key t) (val t)
(insert lt? (lkid t) k v) (rkid t))))
((lt? (key t) k)
(balance (tree (key t) (val t)
(lkid t) (insert lt? (rkid t) k v))))
(else (tree k v (lkid t) (rkid t)))))
(define (delete-successor t)
(if (nil? (lkid t)) (values (rkid t) (key t) (val t))
(call-with-values
(lambda () (delete-successor (lkid t)))
(lambda (l k v)
(values (balance (tree (key t) (val t) l (rkid t))) k v)))))
(define (delete lt? t k)
(cond ((nil? t) nil)
((lt? k (key t))
(balance (tree (key t) (val t)
(delete lt? (lkid t) k) (rkid t))))
((lt? (key t) k)
(balance (tree (key t) (val t)
(lkid t) (delete lt? (rkid t) k))))
((nil? (lkid t)) (rkid t))
((nil? (rkid t)) (lkid t))
(else (call-with-values
(lambda () (delete-successor (rkid t)))
(lambda (r k v) (balance (tree k v (lkid t) r)))))))