平衡二叉树 AVL

三年后的今天,我终于把这个坑填上了。。。

1.插入节点,旋转好像只要调整一次:

  因为需要调整时,必然一侧是n,另一侧是n+2,

  插入之前,必然一侧是n,另一侧是n+1,

  调整之后,两侧都是n+1,整个子树的高度是n+1, 和插入之前相同,

  所有不用再想上找父节点调整

2.删除节点,可能需要多次旋转调整

因为一侧是n,另一侧是n+1,是,删掉n那一侧的节点,调整后可能高度变为n,结果就是整个书的高度-1,要继续在上一层做调整

下面的代码已包含测试

#include <iostream>
#include <cassert>
#include <cmath>
using namespace std;

struct Node
{
	int val;
	Node *left;
	Node *right;
	int layer_children;
	Node(int v):val(v),left(NULL),right(NULL),layer_children(0){}
};

void get_height(Node * node)
{
	int left_layer=0;
	int right_layer=0;
	if(node->left){
		left_layer=node->left->layer_children+1;
	}
	if(node->right){
		right_layer=node->right->layer_children+1;
	}
	node->layer_children=max(left_layer,right_layer);
}
void check_height(Node *node)
{
	int left_layer=0;
	int right_layer=0;
	if(node->left){
		left_layer=node->left->layer_children+1;
	}
	if(node->right){
		right_layer=node->right->layer_children+1;
	}
	assert(node->layer_children==max(left_layer,right_layer));
	assert(abs(left_layer-right_layer)<=1);
}


void rotate_right(Node *& pn){
	Node*n=pn;
	Node*l=n->left;
	Node*lr=l->right;
	pn=l;
	l->right=n;
	n->left=lr;
	get_height(n);
	get_height(l);
	
}
void rotate_left(Node *&pn){
	Node*n=pn;
	Node *r=n->right;
	Node *rl=r->left;
	pn=r;
	r->left=n;
	n->right=rl;
	get_height(n);
	get_height(r);
}

void check(Node *n)
{
	if(n==NULL){
		return;
	}
	if(n->left)
	{
		assert(n->left->val<=n->val);
		check(n->left);
	}
	cout<<n->val<<',';
	if(n->right)
	{
		assert(n->val<=n->right->val);
		check(n->right);
	}
	check_height(n);
}

void adjust(Node *&n)
{
	if(n==NULL){
		return;
	}
	Node *node=n;
	int left_layer=0;
	int right_layer=0;
	if(node->left){
		left_layer=node->left->layer_children+1;
	}
	if(node->right){
		right_layer=node->right->layer_children+1;
	}
	node->layer_children=max(left_layer,right_layer);
	if((left_layer-right_layer)>=2){
		if(node->left->right==NULL|| node->left->left!=NULL  && node->left->left->layer_children>node->left->right->layer_children){
			rotate_right(n);
		}
		else{
			rotate_left((node->left));
			rotate_right(n);
		}
	}
	else if(right_layer-left_layer>=2){
		if(node->right->left==NULL|| node->right->right!=NULL && node->right->right->layer_children>node->right->left->layer_children){
			rotate_left(n);
		}
		else{
			rotate_right((node->right));
			rotate_left(n);
		}
	}
}

void Insert(Node *& root, Node*n)
{
	if(root==NULL){
		root=n;
		return;
	}
	if(n->val<(root)->val){
		Insert((root)->left,n);
	}
	else{
		Insert((root)->right,n);
	}
	Node *node=root;
	adjust(root);
}

bool Delete(Node *&root, int val)
{
	if(root==NULL){
		return false;
	}
	bool suc=true;
	if(val<root->val){
		suc=Delete(root->left,val);
	}
	else if(root->val<val){
		suc=Delete(root->right,val);
	}
	else{
		if(root->left!=NULL){
			Node *t=root->left;
			while(t->right!=NULL){
				t=t->right;
			}
			root->val=t->val;
			Delete(root->left,root->val);
		}else{
			Node *t=root;
			root=root->right;
			delete t;
			
		}
	}
	adjust(root);
	return suc;
}



int main()
{
	Node * root=NULL;
	for(int i=1;i<=100;i++){
		Node *node=new Node(i);
		Insert(root,node);
		check(root);
		cout<<endl;
	}
	for(int i=100;i>=1;i--){
		assert(Delete(root,i));
		check(root);
		cout<<endl;
	}
	return 0;
}

参考:

1.具体的例子和图片说明

http://www.mathcs.emory.edu/~cheung/Courses/323/Syllabus/Trees/AVL-delete.html

2.代码模板

http://blog.csdn.net/cqbzwja/article/details/49965517

https://www.cnblogs.com/pblr/p/5750564.html




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值