C++ 平衡二叉树AVL

平衡二叉树看起来还是挺复杂的,甚至觉得很不可思议,刚开始让我都懵逼了一下。不过后来仔细想想二叉树旋转平衡的原理,感觉还是挺简单的。代码我是在上一篇博文BST的基础上修改,可以看作是BST衍生的分支。我主要实现的还是插入、查找、删除这3个主要方法,从数据结构上来说,Node节点仅仅多了记录高度height(包含自身)这一个字段,如果不考虑删除方法的话,其实连这一个字段都可以不用添加,可以用轻微左倾,如果再轻微左倾上插入左节点,abs(平衡因子)就会大于1,此时作为平衡检测的条件点。当然,我代码中直接加入了height字段,只需用abs(左子-右子)判断平衡因子是否大于1即可作为平衡检测的条件,不平衡则调用cw(顺时针)、ccw(逆时针)旋转使其平衡即可。旋转又分为几种情况,具体我就不再阐述,看代码即可。删除和BST有一点不同,就是需要再递归返回的时候刷新下高度,并且还要做平衡检测,若不平衡则需再次平衡,所以还不能像BST直接调search找节点来删除,必须在内部实现,递归返回判断是否删除了节点,若删除,则刷新依次从下到上走过节点的高度,并处理平衡。还有就是我对于有左子右子要删除的节点,我用的是后继删除,在寻找最左时用stack LIFO去处理走过的节点,网上很多版本都有BUG,我这个测试是绝对没BUG的

#include<iostream>
#include<ctime>
#include<stack>

using namespace std;

struct Node{
	int data;
	int height;
	Node* left;
	Node* right;
};

void InOrderTranversal(Node* root){
	
	if(root==0){
		return;
	}
	
	InOrderTranversal(root->left);
	
	cout<<root->data<<':'<<root->height<<endl;
	
	InOrderTranversal(root->right);
		
}

void release(Node* root){
	
	if(root==0){
		return;
	}
	
	release(root->left);
	release(root->right);
	
	delete root;
		
}

void search(Node*& root,int key,Node**& _result){
	
	if(root==0){
		_result=0;
		return;
	}
	
	if(key<root->data){
		search(root->left,key,_result);
	}
	else if(key==root->data){
		_result=&root;//put purpoes's addr to result for changing the purpoes pointer point another addr by _delete
		return;
	}
	else{
		search(root->right,key,_result);
	}
	
}

int getBalanceFactor(Node* root){
	int val;
	if(root->left!=0&&root->right!=0){
		val=root->left->height-root->right->height;
	}
	else if(root->left!=0){
		val=root->left->height;
	}
	else if(root->right!=0){
		val=-root->right->height;
	}
	return val;
}

void calculateHeight(Node* root){
	if(root->left!=0&&root->right!=0){
		root->height=root->left->height>root->right->height?root->left->height+1:root->right->height+1;
	}
	else if(root->left!=0){
		root->height=root->left->height+1;
	}
	else if(root->right!=0){
		root->height=root->right->height+1;
	}
	else{
		root->height=1;
	}
}

void cwSpin(Node*& root){

	if(root->left->left==0){
		Node* mid=root->left;
		root->left=root->left->right;
		root->left->left=mid;
		mid->right=0;
		
		calculateHeight(root->left->left);
		calculateHeight(root->left);
	}
	
	Node* ori_root=root;
	root=root->left;
	Node* beta=root->right;
	root->right=ori_root;
	
	if(beta!=0){
		ori_root->left=beta;
	}
	else{
		ori_root->left=0;
	}
	calculateHeight(ori_root);
}

/* ccwSpin:
					1
	alpha					2
					beta			3
				
					|
					|
					|
					¡ý
		
					2
	 		1				3
	alpha		beta
*/

void ccwSpin(Node*& root){
	
	if(root->right->right==0){
		Node* mid=root->right;
		root->right=root->right->left;
		root->right->right=mid;
		mid->left=0;
		
		calculateHeight(root->right->right);
		calculateHeight(root->right);
	}
	
	
	//alpha doesn't need to move
	Node* ori_root=root;
	root=root->right;
	Node* beta=root->left;
	root->left=ori_root;
	if(beta!=0){
		ori_root->right=beta;
	}
	else{
		ori_root->right=0;
	}
	
	calculateHeight(ori_root);
}

bool insert(Node*& root,int value){
	
	if(root==0){
		root=new Node;
		root->left=0;
		root->right=0;
		root->data=value;
		root->height=1;
		return true;
	}
	
	if(value>root->data){
		if(!insert(root->right,value)){
			return false;
		}
		else{
			int bf=getBalanceFactor(root);
			if(bf==-2){
				cout<<"right need balance!"<<endl;
				ccwSpin(root);
			}
		}
	}
	else if(value==root->data){
		return false;
	}
	else{
		if(!insert(root->left,value)){
			return false;
		}
		else{
			int bf=getBalanceFactor(root);
			if(bf==2){
				cout<<"left need balance!"<<endl;
				cwSpin(root);
			}
		}
	}
	
	calculateHeight(root);
	return true;
}
bool _delete(Node*& root,int key){
	
	if(root==0){
		return false;
	}
	
	if(key<root->data){
		if(_delete(root->left,key)){
			calculateHeight(root);
			int bf=getBalanceFactor(root);
			if(bf==2){
				cwSpin(root);
			}
			if(bf==-2){
				ccwSpin(root);
			}
			calculateHeight(root);
			return true;
		}
		else{
			return false;
		}
	}
	else if(key==root->data){
		
		
		Node* temp=root;
	
		if(root->left==0&&root->right==0){//leaf node can remove now
			root=0;
			delete temp;
		}
		else if(root->left==0){//if has no left,make parent link to right and remove itself
			root=root->right;
			delete temp;
		}
		else if(root->right==0){
			root=root->left;
			delete temp;
		}
		else{
			//it must have left and right
			//my method is subsequent move,walk to end of right's left
			//s init to right
			//s_prent init to root
			Node* s=root->right;
			Node* s_parent=root;
			stack<Node**> _stack;
			_stack.push(&root);
			bool first=true;
			while(s->left!=0){

				if(first){
					_stack.push(&s_parent->right);
				}
				else{
					_stack.push(&s_parent->left);
				}
				
				s_parent=s;
				s=s->left;
				first=false;
			}
		
			temp->data=s->data;
		
			if(s->right!=0){//if end of right's left has right, it should replace end of right's left
				if(s_parent==root){//if s_parent does not change,s_parent has had left tree,so it should put s'right to s_parent's right
					s_parent->right=s->right;
				}
				else{
					s_parent->left=s->right;
				}
			}
			else{
				if(s_parent==root){
					s_parent->right=0;
				}
				else{
					s_parent->left=0;
				}
			}
		
			while(_stack.size()>0){
			
				calculateHeight(*_stack.top());
	
				int bf=getBalanceFactor(*_stack.top());
				if(bf==2){
					cwSpin(*_stack.top());
				}
				if(bf==-2){
					ccwSpin(*_stack.top());
				}
				
				calculateHeight(*_stack.top());

				_stack.pop();
			
			}
			
			delete s;
		
		}
		
		return true;
	}
	else{
		if(_delete(root->right,key)){
			calculateHeight(root);
			int bf=getBalanceFactor(root);
			if(bf==2){
				cwSpin(root);
			}
			if(bf==-2){
				ccwSpin(root);
			}
			calculateHeight(root);
			return true;
		}
		else{
			return false;
		}
	}
	
}

int main(){
	
	srand(time(NULL));
	
	Node* root=new Node;
	root->left=0;
	root->right=0;
	root->data=10;
	

	for(int i=0;i<100;i++){
		insert(root,rand()%100);
	}
	


	InOrderTranversal(root);
	
	Node** _result;
	
	int value;
	cout<<"please cin the value you want to find:";
	cin>>value;
	
	search(root,value,_result);


	if(_result==0){
		cout<<"can't find purpoes!"<<endl;
	}
	else{
		cout<<"the result is:"<<(*_result)->data<<endl; 
	}
	

		
	cout<<"please cin the value you want to delete:";
	cin>>value;
	
	if(_delete(root,value)){
		InOrderTranversal(root);
		cout<<"delete succeed!"<<endl;
	} 
	else{
		cout<<"delete failed!"<<endl;
	}


	
	release(root);
	
	return 0;
}

    原文作者:平衡二叉树
    原文地址: https://blog.csdn.net/nightwizard2030/article/details/72874715
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞