平衡二叉树的建立查考插入删除操作

      如果二叉排序树的左、右子树的高度之差的绝对值不超过1,这样的排序二叉树称为平衡二叉树,它的平均查找长度达到O(log2n)。

      为了避免树的高度增长过快,降低二叉排序树的性能,我们规定在插入和删除二叉树结点时,要保证任意结点的左、右子树高度差的绝对值不超过1。这样的二叉树称为平衡二叉树。

      平衡二叉树可定义为它或是一棵空树,或者是具有下列性质的二叉树:它的左子树和右子树都是平衡二叉树,且左子树和右子树的高度差的绝对值不超过1。

     需要注意的有以下两点:

插入操作中:

      LR和RL旋转的时候,调用LL和RR旋转,其原因是这样做复合LR和RL的最终要求,这里调用LL(RR)旋转函数,不是说

在左子树的左子树(右子树的右子树)插入了结点,而只是为了可以达到LR(RL)的最终形态。这里也可以不调用LL和RR函数,对指针进行操作也可以,不过需要对四代指针进行操作,比较麻烦。

删除操作(难点):

      同插入操作一样,删除结点时也有可能破坏平衡性,这就要求我们删除的时候要进行平衡性调整。

      删除分为以下几种情况:

      首先在整个二叉树中搜索要删除的结点,如果没搜索到直接返回不作处理,否则执行以下操作:

           1.要删除的节点是当前根节点T。

             如果左右子树都非空。在高度较大的子树中实施删除操作。

                分两种情况:

                 (1)、左子树高度大于右子树高度,将左子树中最大的那个元素赋给当前根节点,然后删除左子树中元素值最大的那个节点。

                  (2)、左子树高度小于右子树高度,将右子树中最小的那个元素赋给当前根节点,然后删除右子树中元素值最小的那个节点。

             如果左右子树中有一个为空,那么直接用那个非空子树或者是NULL替换当前根节点即可。

          2、要删除的节点元素值小于当前根节点T值,在左子树中进行删除。

               递归调用,在左子树中实施删除。这个是需要判断当前根节点是否仍然满足平衡条件,如果满足平衡条件,只需要更新当前根节点T的高度信息。否则,需要进行旋转调整:如果T的左子节点的左子树的高度大于T的左子节点的右子树的高度,进行相应的单旋转。否则进行双旋转。

           3、要删除的节点元素值大于当前根节点T值,在右子树中进行删除。

#include <iostream>
#include <queue>
#include <stack>
using namespace std;

template <typename T>
struct avlTreeNode{
	T data;
	int height;
	avlTreeNode* left;
	avlTreeNode* right;
	avlTreeNode(T val, avlTreeNode<T>* l, avlTreeNode<T>* r):data(val), height(0), left(l), right(r){}
};

template <typename T>
class avlTree{
private:
	avlTreeNode<T>* root;
	int max(int a, int b){return a > b ? a : b;}
public:
	avlTree(){root = NULL;}
	avlTreeNode<T>*& getRoot(){return root;}
	int getHeight(avlTreeNode<T>* ptr);//获得子树的高度
	void llRotation(avlTreeNode<T>* &root);//对以root为根节点的最小不平衡子树进行LL平衡旋转
	void lrRotation(avlTreeNode<T>* &root);//对以root为根节点的最小不平衡子树进行LR平衡旋转
	void rrRotation(avlTreeNode<T>* &root);//对以root为根节点的最小不平衡子树进行RR平衡旋转
	void rlRotation(avlTreeNode<T>* &root);//对以root为根节点的最小不平衡子树进行RL平衡旋转
	void addValue(avlTreeNode<T>* &root, T val);//向平衡树中增加结点
	void delValue(avlTreeNode<T>* &root, T val);//删除值val所在结点
	void creatAvlTree();//建立平衡树
	avlTreeNode<T>* getMin(avlTreeNode<T>* root) const;//找到以root为根节点的树中最小的节点
	avlTreeNode<T>* getMax(avlTreeNode<T>* root) const;//找到以root为根节点的树中最大的节点
	void printAvlTreeOfPre() const;//先序遍历输出结果
	void printAvlTreeOfIn() const;//中序遍历输出结果
};

template <typename T>
int avlTree<T>::getHeight(avlTreeNode<T>* ptr){
	if(ptr != NULL)
		return ptr -> height;
	return 0;
}

template <typename T>
void avlTree<T>::llRotation(avlTreeNode<T>* &root){
	//进行右单旋转,这里需要注意的是需要对两个结点的高度进行调整
	avlTreeNode<T>* temp = root;

	root = root -> left;
	temp -> left = root -> right;
	root -> right = temp;
	
	temp -> height = max(getHeight(temp -> left), getHeight(temp -> right)) + 1;
	root -> height = max(getHeight(root -> left), getHeight(root -> right)) + 1;
}

template <typename T>
void avlTree<T>::rrRotation(avlTreeNode<T>* &root){
	//进行左单旋转,这里需要注意的是需要对两个结点的高度进行调整
	avlTreeNode<T>* temp = root;

	root = root -> right;
	temp -> right = root -> left;
	root -> left = temp;
	
	temp -> height = max(getHeight(temp -> left), getHeight(temp -> right)) + 1;
	root -> height = max(getHeight(root -> left), getHeight(root -> right)) + 1;
}

template <typename T>
void avlTree<T>::lrRotation(avlTreeNode<T>* &root){
	//先进行左旋转,在进行右旋转
	rrRotation(root -> left);
	llRotation(root);
}

template <typename T>
void avlTree<T>::rlRotation(avlTreeNode<T>* &root){
	//先进行左旋转,在进行右旋转
	llRotation(root -> right);
	rrRotation(root);
}

template <typename T>
void avlTree<T>::addValue(avlTreeNode<T>* &root, T val){
	if(root == NULL){//根节点是NULL
		root = new avlTreeNode<T>(val, NULL, NULL);
	}else if(root -> data > val){//插入到左子树
		addValue(root -> left, val);
		if(getHeight(root -> left) - getHeight(root -> right) == 2){
			if(root -> left -> data > val){
				llRotation(root);
			}else{
				lrRotation(root);
			}
		}
	}else if(root -> data < val){//插入到右子树
		addValue(root -> right, val);
		if(getHeight(root -> left) - getHeight(root -> right) == -2){
			if(root -> right -> data > val){
				rlRotation(root);
			}else{
				rrRotation(root);
			}
		}
	}else{
		cout << "平衡树中已有该结点" <<endl;
	}

	root -> height = getHeight(root -> left) > getHeight(root -> right) ? getHeight(root -> left) + 1:getHeight(root -> right) + 1;
}

template <typename T>
void avlTree<T>::creatAvlTree(){
	T val;
	cin >> val;
	
	while(val != '#'){
		addValue(root, val);
		cin >> val;
	}
}

template <typename T>
void avlTree<T>::delValue(avlTreeNode<T>* &root, T val){
	if(root == NULL)//树中没有值为val的节点
		return;
	if(root -> data == val){
		if(root -> left != NULL && root -> right != NULL){
			//左子树高度大,删除左子树中值最大的结点,将其赋给根结点
			if(getHeight(root -> left) > getHeight(root -> right)){
				root -> data = getMax(root -> left) -> data;
				delValue(root -> left, root -> data);
			}else{//右子树高度更大,删除右子树中值最小的结点,将其赋给根结点
				root -> data = getMin(root -> right) -> data;
				delValue(root -> right, root -> data);
			}
		}else{//左右子树有一个不为空,直接用需要删除的结点的子结点替换即可
			avlTreeNode<T>* temp = root;
			root = root -> left == NULL ? root -> right: root -> left;
			delete temp;
		}

	}else if(root -> data < val){//在root的右子树删除val
		delValue(root -> right, val);

		if(getHeight(root -> right) - getHeight(root -> left) == -2){//需要进行调整
			if(getHeight(root -> left -> left) > getHeight(root -> left -> right)){
				llRotation(root);
			}else{
				lrRotation(root);
			}

		}else{//不需要调整
			root -> height = max(getHeight(root -> right), getHeight(root -> left)) + 1;
		}

	}else if(root -> data > val){//在root的左子树删除val
		delValue(root -> left, val);

		if(getHeight(root -> right) - getHeight(root -> left) == 2)
		{//需要进行调整
			if(getHeight(root -> right -> left) > getHeight(root -> right -> right)){
				rlRotation(root);
			}else{
				rrRotation(root);
			}
		}else{//不需要调整
			root -> height = max(getHeight(root -> right), getHeight(root -> left)) + 1;
		}
	}
}

template <typename T>
avlTreeNode<T>* avlTree<T>::getMin(avlTreeNode<T>* root) const{//找到以root为根节点的树中最小的节点
	if(root == NULL)
		return NULL;
	while(root -> left != NULL){
		root = root -> left;
	}
	return root;
}

template <typename T>
avlTreeNode<T>* avlTree<T>::getMax(avlTreeNode<T>* root) const{//找到以root为根节点的树中最大的节点
	if(root == NULL)
		return NULL;
	while(root -> right != NULL){
		root = root -> right;
	}
	return root;
}

template <typename T>
void avlTree<T>::printAvlTreeOfPre() const{
	if(root == NULL)
		return;
	stack <avlTreeNode<T>*> stc;
	stc.push(root);

	while(!stc.empty()){
		avlTreeNode<T>* temp = stc.top();
		stc.pop();
		cout << temp -> data << " ";

		if(temp -> right != NULL){
			stc.push(temp -> right);
		}

		if(temp -> left != NULL){
			stc.push(temp -> left);
		}
	}
}

template <typename T>
void avlTree<T>::printAvlTreeOfIn() const{
	if(root == NULL)
		return;
	stack <avlTreeNode<T>*> stc;
	avlTreeNode<T>* temp = root;
	while(!stc.empty() || temp != NULL){
		if(temp != NULL){
			stc.push(temp);
			temp = temp -> left;
		}else{
			temp = stc.top();
			stc.pop();
			cout << temp -> data << " ";
			temp = temp -> right;
		}
	}
}

int main(){
	avlTree<char>* tree = new avlTree<char>;
	tree -> creatAvlTree();
	cout<<endl<<"前序遍历结果:"<<endl;
	tree -> printAvlTreeOfPre();
	cout<<endl<<"中序遍历结果:"<<endl;
	tree -> printAvlTreeOfIn();
	cout<<endl;
	tree -> delValue(tree -> getRoot(), 'a');
	cout<<endl<<"删除结点a之后的前序遍历结果:"<<endl;
	tree -> printAvlTreeOfPre();
	cout<<endl<<"删除结点a之后的中序遍历结果:"<<endl;
	tree -> printAvlTreeOfIn();
	cout<<endl;
	return 0;
}

测试结果如下:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值