1. 程式人生 > >SBTree的概念以及程式碼實現

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;
}