二叉搜索樹的複雜度分析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);
}
複製代碼
喜歡的能夠關注下個人公衆號,會在第一時間更新