AVL平衡二叉搜索树

AVL tree是一个“加上了额外平衡条件”的二叉搜索树。其平衡条件的建立是为了确保整棵树的深度为O(logN)。平衡二叉搜索树的大部分实现与普通的二叉搜索树相同,区别在于插入和删除节点之后需要对节点做一个旋转操作来维持平衡。

侯捷先生在STL源码剖析中提到,直观上的最佳平衡条件是每个节点的左右子树有着相同的高度,但这也未免太过严苛,我们很难插入新元素而又保持这样的平衡条件。AVL tree于是退而求其次,要求任何节点的左右子树高度相差最多1。

对二叉树的平衡调整过程,主要包含四种旋转操作:LL,LR,RR,RL 。
LL(左左):插入点位于 X 的左子节点的左子树
LR(左右):插入点位于 X 的左子节点的右子树
RR(右右):插入点位于 X 的右子节点的右子树
RL(右左):插入点位于 X 的右子节点的左子树

下面是AVL平衡二叉树的代码实现:

#include 
   
   
    
    
#include 
    
    
     
     
#include 
     
     
      
      

using namespace std;

struct AVLTreeNode {
	int val;
	AVLTreeNode* left;
	AVLTreeNode* right;
	int height;			//子树的高度
};

void makeEmpty(AVLTreeNode* T) {
	if (T == NULL)
		return;
	else {
		makeEmpty(T->left);
		makeEmpty(T->right);
		delete(T);
	}
}

int _Height(AVLTreeNode* T) {
	if (T == NULL)
		return 0;
	else
		return T->height;
}

int _Max(int n1, int n2) {
	return n1 > n2 ? n1 : n2;
}

//LL == 右旋转
AVLTreeNode* single_rotate_LL(AVLTreeNode* k2) {
	AVLTreeNode* k1 = k2->left;
	k2->left = k1->right;
	k1->right = k2;
	k2->height = _Max(_Height(k2->left), _Height(k2->right)) + 1;
	k1->height = _Max(_Height(k1->left), k2->height) + 1;
	return k1;
}

//RR == 左旋转
AVLTreeNode* single_rotate_RR(AVLTreeNode* k1) {
	AVLTreeNode* k2 = k1->right;
	k1->right = k2->left;
	k2->left = k1;
	k1->height = _Max(_Height(k1->left), _Height(k1->right)) + 1;
	k2->height = _Max(k1->height, _Height(k2->right)) + 1;
	return k2;
}

//LR == 先将 k3 的左子节点进行左旋转,再对 k3 右旋转
AVLTreeNode* double_rotate_LR(AVLTreeNode* k3) {
	k3->left = single_rotate_RR(k3->left);
	return single_rotate_LL(k3);
}

//RL == 先将 k3 的右子节点进行右旋转,再对 k3 左旋转
AVLTreeNode* double_rotate_RL(AVLTreeNode* k4) {
	k4->right = single_rotate_LL(k4->right);
	return single_rotate_RR(k4);
}

AVLTreeNode* AVL_insert(AVLTreeNode* T, int value) {
	if (T == NULL) {
		T = new AVLTreeNode;

		if (T == NULL) {
			cout << "ERROR: creat AVL node failed !" << endl;
			return NULL;
		}

		T->val = value;
		T->left = NULL;
		T->right = NULL;
		T->height = 0;
	}

	else if (value < T->val) {
		T->left = AVL_insert(T->left, value);

		//插入元素之后,若 T 的左子树比右子树高度 之差是 2,即不满足 AVL平衡特性,需要调整
		if (_Height(T->left) - _Height(T->right) == 2) {
			if (value < T->left->val)
				T = single_rotate_LL(T);	//把x插入到了T->left的左侧,只需 左侧单旋转 -- LL旋转
			else
				T = double_rotate_LR(T);	// x 插入到了T->left的右侧,需要左侧双旋转 
		}
	}

	else if (value > T->val) {
		T->right = AVL_insert(T->right, value);

		if (_Height(T->right) - _Height(T->left) == 2) {
			if (value > T->right->val)
				T = single_rotate_RR(T);
			else
				T = double_rotate_RL(T);
		}
	}

	else if (value == T->val) {
		cout << "添加失败,不能添加相同的节点" << endl;
	}

	T->height = _Max(_Height(T->left), _Height(T->right)) + 1;

	return T;
}

//对单个节点进行的AVL调整
AVLTreeNode* AVL_balance(AVLTreeNode* T) {
	if (_Height(T->left) - _Height(T->right) == 2) {
		if (_Height(T->left->left) >= _Height(T->left->right))
			T = single_rotate_LL(T);
		else
			T = double_rotate_LR(T);
	}

	if (_Height(T->right) - _Height(T->left) == 2) {
		if (_Height(T->right->right) >= _Height(T->right->left))
			T = single_rotate_RR(T);
		else
			T = double_rotate_RL(T);
	}

	return T;
}

/**
  * 首先定位要删除的节点,然后用该节点的右孩子的最左孩子替换该节点,
  * 并重新调整以该节点为根的子树为AVL树,具体调整方法跟插入数据类似
  * 删除处理在整体上耗费O(log n) 时间。
*/
AVLTreeNode* AVL_delete(AVLTreeNode* T, int value) {
	if (T == NULL)
		return NULL;

	else if (value < T->val)
		T->left = AVL_delete(T->left, value);
	
	else if (value > T->val)
		T->right = AVL_delete(T->right, value);

	else if (value == T->val) {
		if (T->right == NULL) {
			AVLTreeNode* temp = T->left;
			//T = T->left;
			//T = (T->left != NULL) ? T->left : T->right;
			delete T;
			return temp;
		}
		else {
			AVLTreeNode* temp = T->right;
			while (temp->left) {
				temp = temp->left;
			}
			T->val = temp->val;
			T->right = AVL_delete(T->right, T->val);
			//T->height = _Max(_Height(T->left), _Height(T->right)) + 1;
		}
		return T;
	}
	
	//当删除元素后调整平衡
	if (T->left != NULL)
		T->left = AVL_balance(T->left);
	if (T->right != NULL)
		T->right = AVL_balance(T->right);
	if (T != NULL)
		T = AVL_balance(T);

	T->height = _Max(_Height(T->left), _Height(T->right)) + 1;
	return T;
}

void inOrder(AVLTreeNode* T) {
	if (T == NULL)
		return;

	stack
      
      
       
        s;
	AVLTreeNode* node = T;

	while (node != NULL || !s.empty()) {
		while (node != NULL) {
			s.push(node);
			node = node->left;
		}

		node = s.top();
		cout << node->val << " ";
		s.pop();

		if (node->right == NULL)
			node = NULL;
		else
			node = node->right;
	}

	cout << endl;
}

int main() {
	AVLTreeNode* T = NULL;
	int a[] = { 3, 2, 1, 4, 5, 6, 7, 16, 15, 14, 13, 12, 11, 10, 8, 9 };

	for (int i = 0; i < 16; i++) {
		T = AVL_insert(T, a[i]);
	}

	preOrder(T);
	inOrder(T);
	postOrder(T);
	
	AVLTreeNode* temp;
	temp = AVL_delete(T, 7);
	inOrder(temp);
	
	return 0;
}
      
      
     
     
    
    
   
   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值