三年后的今天,我终于把这个坑填上了。。。
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.youkuaiyun.com/cqbzwja/article/details/49965517
https://www.cnblogs.com/pblr/p/5750564.html
962

被折叠的 条评论
为什么被折叠?



