LLRB 左倾红黑树(四)其他
Robert Sedgewick的左倾红黑树,
书上讲解太粗略,看不明白,好不容昂找来他的pdf,发现还是不够详细。按照作者的说法,左倾红黑树代码量少。但实际上呢,左倾红黑树的情况非常多,光2-3树,2-3-4树,2-3-4-5树的可能情况就说不完,我个人觉得作者故意忽略好多细节,因为要讲,肯定篇幅太长;而且为了简略而简略,造成有些代码太过简略而难以理解。比如delete()方法,这里为了减少代码量,把大于key和等于key的情况都放到最外面的else里面,这显然会增加代码理解难度。
private Node delete(Node h, Key key)
{
if (less(key, h.key))
{
if (!isRed(h.left) && !isRed(h.left.left))
h = moveRedLeft(h);
h.left = delete(h.left, key);
}
else
{
if (isRed(h.left))
h = rotateRight(h);
if (eq(key, h.key) && (h.right == null))
return null;
if (!isRed(h.right) && !isRed(h.right.left))
h = moveRedRight(h);
if (eq(key, h.key))
{
h.value = get(h.right, min(h.right));
h.key = min(h.right);
h.right = deleteMin(h.right);
}
else h.right = delete(h.right, key);
}
return fixUp(h);
}
这方面,我反而觉得传统红黑树更好一些,因为传统方法就是穷举,虽然情况多,但穷举完了就完了,没有其他可能性了。而不是像这个左倾红黑树,好多情况没有说明。
我在写作这篇文章的时候,总有种,编不下去了的感觉。
另外,网上有一个反对LLRB的文章,http://www.read.seas.harvard.edu/~kohler/notes/llrb.html。作者Eddie Kohler认为LLRB的主要问题,有以下几点
- 父指针缺失。有父指针,可以非常容易找到节点前继和后继。删除父指针,速度提升不明显;
- 过多的旋转。算法导论上严格界定,插入的旋转不超过2次,删除的旋转不超过3次。LLRB在自顶向下和自底向上的过程中都会旋转,自顶向下即从根节点递归到目标节点的过程;自底向上即,在找到目标节点后,从目标节点返回根节点时,调用fixUp
- LLRB的插入、删除、查找performance都要比普通红黑树慢;(performance应该是指速度)
- LLRB的的实现并非像其所说的那样简化;算法导论上的左旋和右旋是对称的(symmetric),只需要一个旋转实现即可;而LLRB的左旋和右旋是不对称的(asymmetric),必须分开实现。
Robert Sedgewick的LLRB的课件,57页,deletaMax()的代码中,有一句代码错了,
h.left = deleteMax(h.left); // 原pdf57页错误 h.right = deleteMax(h.right) // 正确的代码
参考文章:
http://www.cs.princeton.edu/~rs/talks/LLRB/Java/
https://blog.csdn.net/qy844083265/article/details/80716065

浙公网安备 33010602011771号