二叉搜索树的复杂度分析java
和高度有关node
O(h) = O(logn)spa
最坏复杂度是从小到大添加节点 (和链表差很少)code
O(h) = O(n)cdn
如何二叉搜索树退化成链表??blog
让添加删除搜索的复杂度维持在logn进程
当节点固定时,左右字数高度就越接近,这可二叉树就越平衡it
最理想的平衡,例如 彻底二叉树,满二叉树io
由于没法改变添加删除顺序(用户操做决定),因此在每次操做以后,让二叉树达到平衡状态。function
简称BBST
常见的平衡二叉搜索树有
通常称他们为:自平衡的二叉搜索树(Self-Balance Binary Search Tree)
最先发明的自平衡二叉树之一
取名为G.M.Adelson-Velsky和E.M.Landis(来自苏联的科学家) 两我的的名字称呼
平衡因子:某节点的左右子树高度差
注意维护T三、二、3的 parent的属性
以及更新二、3的高度
注意维护T三、三、4的 parent的属性
以及更新三、4的高度
对旋转后对3进行LL右旋转
参考上方LL右旋转
在删除后进行平衡操做
让父节点恢复失衡后,可能致使更高节点的祖先接点失衡(最多须要log(n)次调整)
添加会致使全部祖先节点都失衡
处理:只要让最低失衡节点回复平衡,整棵树就回复平衡(O(n))
添加后进行平衡操做
搜索:平均时间复杂度O(logn)
添加:平均时间复杂度O(logn) O(1)次旋转
删除:平均时间复杂度O(logn) O(logn)次旋转
private void rebalance(Node<E> grand) {
// 获取子节点最高的节点
Node<E> parent = ((AVLNode<E>)grand).tallChild();
// 获取子节点的子节点中最高的节点
Node<E> node = ((AVLNode<E>)parent).tallChild();
// 判断旋转状况
if (parent.isLeftChild() ) { //L
if (node.isLeftChild()) { //LL
rotateRight(grand);
}else { //LR
rotateLeft(parent);
rotateRight(grand);
}
}else { //R
if (node.isLeftChild()) { //RL
rotateRight(parent);
rotateLeft(grand);
}else { //RR
rotateLeft(grand);
}
}
}
// RR 右旋转
private void rotateLeft(Node<E> grand) {
Node<E> parent = grand.right;
Node<E> child = parent.left;
grand.right = child;
parent.left = grand;
afterRotate(grand, parent, child);
}
// LL 左旋转
private void rotateRight(Node<E> grand) {
Node<E> parent = grand.left;
Node<E> child = parent.right;
grand.left = child;
parent.right = grand;
afterRotate(grand, parent, child);
}
// 旋转后更新操做(更新parent节点),更新高度等;
private void afterRotate(Node<E> grand,Node<E> parent, Node<E> child) {
parent.parent = grand.parent;
if (grand.isLeftChild()) {
grand.parent.left = parent;
}else if (grand.isRightChild()){
grand.parent.right = parent;
}else {
root = parent;
}
if (child != null) {
child.parent = grand;
}
grand.parent = parent;
updateHeight(grand);
updateHeight(parent);
}
复制代码
喜欢的能够关注下个人公众号,会在第一时间更新