SBTree的概念以及程式碼實現
SBTree與AVL樹具有相同的概念,也具有相同的操作類似自平衡,旋轉操作和旋轉的觸發這三方面介紹SBTree
SBTree嚴格遵循下列公式,如有違反,則需要通過相應的轉置操作來達到平衡
SIZE[right[t]] >= max(SIZE[left[left[t]]], SIZE[right[left[t]]]);
SIZE[left[t]] >= max(SIZE[left[right[t]]], SIZE[right[right[t]]])
其中SIZE[t]表示t結點所在的子樹個數,且兩個公式必須同時滿足
SIZE[left[left[t]]]可以表示成t->left->left,SIZE[right[left[t]]])可表示成t->left->right
這兩個公式可能有點難理解:簡單來說就是每個結點所在的子樹(分左子樹和右子樹)的結點個數不小於其兄弟的兩個孩子所在子樹的結點個數
比如說39這個結點,它的右子樹結點個數為2,它的兄弟結點的左右子樹個數最大值為1,2>1,成立
但是,它的左子樹結點個數為0,0<1,不能同時滿足兩個公式
所以這裡39要進行左旋操作
SBTree的調整方法:
(1)LL型:(SIZE[left[left[t]]] > size[right[t]])
這種情況種,左子樹的左子樹比右子樹個數要大,會發生不平衡,
首先對子樹進行右旋操作,旋轉後對t的右子樹進行調整,之後再對子樹t進行調整
(2)LR型:(SIZE[right[left[t]]] > size[right[t]])
首先對t的左子樹執行左旋操作,再對t進行右旋操作,之後分別調整結點t的左右子樹,最終調整整條子樹
(3)RR型:(SIZE[right[right[t]]] > size[left[t]])
首先對t的右子樹進行左旋,然後分別進行調整
(4)RL型:(SIZE[left[right[t]]] > size[left[t]])
首先對右子樹進行右旋操作,然後對左子樹進行左旋操作
相關程式碼的實現
我們在二叉搜尋樹的基礎上增加左旋,右旋,維護功能,就實現了一個SBTree
首先給出左旋演算法,
SBTNode* mleft_rotate(SBTNode* node) { //左旋操作
SBTNode* temp = node->rchild;
node->rchild = temp->lchild;
temp->lchild->father = node;
temp->lchild = node;
temp->father = node->father;
node->father = temp;
return nullptr;
}
右旋演算法與左旋演算法類似:
SBTNode* mright_rotate(SBTNode* node) { //右旋操作
SBTNode* temp = node->lchild;
node->lchild = temp->rchild;
temp->rchild->father = node;
temp->rchild = node;
temp->father = node->father;
node->father = temp;
return nullptr;
}
這兩個演算法相對來說比較好理解,作為模板記下即可,在旋轉過後,我們還要對結點進行維護操作
SBTree的調整與優化:
在插入後,一共有4種除法旋轉的情況,分為LL型,LR型,RR型,RL型,RR型
在我們之前給出的公式種:
A:SIZE[right[t]] >= max(SIZE[left[left[t]]], SIZE[right[left[t]]]);
B:SIZE[left[t]] >= max(SIZE[left[right[t]]], SIZE[right[right[t]]]);
LL,LR違反了平衡條件A,RR和RL違反了平衡條件B
對應的,LL,LR能夠保證b成立,RR,RL能夠保證a成立,所以條件就可以這樣進行篩選
維護演算法如下:
(1)處理左子樹更高的情況
(1)LL型:右旋t
(2)LR型:左旋t的左子樹,再右旋t
(2)處理右子樹更高的情況
(1)RL型:右旋t的右子樹,再左旋
(2)RR型:左旋t
(3)遞迴進行相應的維護
遞迴調整左子樹中左子樹的左子樹更高的情況
遞迴調整右子樹中右子樹的右子樹更高的情況
遞迴調整當前子樹中左子樹更高的情況
遞迴調整當前子樹中右子樹更高的情況
template <typename Type>
SBTNode<Type>* maintain(SBTNode<Type>* node, bool flag) {
if (flag == false) {
if (node->lchild->lchild->size > node->rchild->size) { //LL型樹
node = right_rotate(node);
}
else if (node->lchild->rchild->size > node->rchild->size) { //LR型樹
node->lchild = left_rotate(node->lchild);
node = right_rotate(node);
}
else {
return node; //正常結點,直接返回即可
}
}
else {
if (node->rchild->rchild->size > node->lchild->size) { //RR型
node = left_rotate(node);
}
else if (node->rchild->lchild->size > node->lchild->size) {
node->rchild = right_rotate(node->rchild);
node = left_rotate(node);
}
else {
return node;
}
}
node->lchild = maintain(node->lchild, false);
node->rchild = maintain(node->rchild, true);
maintain(node, false);
maintain(node, true);
return node;
}