在AVL树中,为了避免每次计算左右子树的高度,我们可以采用balancefactor来判断,我们将balancefactor定义为左子树的高度减去右子树的高度;
---------------------------------------------------------
---------------------------插入---------------------------
---------------------------------------------------------
1在插入的过程中,我们可以先通过普通二叉树的插入方法将节点p插入到合适的位置,然后对于检查其父母current:
-
如果current的key小于p的key,那么证明p是current的 右儿子,那么current的balancefactor应该减1;
-
如果current的key大于p的key,那么证明p是current的右儿子,那么current的balancefactor应该加1;
-
如果current等于NULL或者current的factor等于0,停止
-
否则,current指向其父节点。
这个时候我开始有点担心会不会出现以下这种情况:
在插入55的过程中,
45的factor会不会变呢?
其实是不会的,因为我们在(3)中检查了current的facotr是否为0,如果为0,就停止循环。
2在此过程中,我们还要检查插入后是否仍然满足AVL树的性质,那么我们可以这样检查:
(1)如果current的factor等于2,那么证明p插入到了current的左儿子上t,那么t的factor只能有两种情况,一种是1,一种是-1(显然不可能为2,而为0的就已经停止循环了),
如果t的factor为1,那么证明p插入到了leftsubtree of left
child.此时应对current用一次右旋转。
如果t的factor为-1,那么证明p插入到了rightsubtree of left child。此时应先对t进行一次左旋转,在对current进行一次右旋转。
(2)如果current的factor等于-2,则情况与上述情况类似,只不过左右的情况相反。
3在旋转过程中,我们也许要对balancefactor进行调整:
显然只有x和y的factor会受到影响。
对于左旋转:αβϒ
旋转前:x->bf=α – 1 - max(β,ϒ)
y->bf= β-ϒ
旋转后:x->bf= α-β
y->bf= 1 + max(α,β) - ϒ
那么显然:
如果y->bf大于等于0,即β>ϒ,那么旋转后
x->bf= x->bf + 1;
否则
x->bf= x->bf – y->bf + 1;
总结即是:
++x->bf-= y->bf >= 0 ? 0 : y->bf;
同理,++y->bf+= x->bf > 0 ? x->bf : 0;
对于右旋转:
同理:--(y->bf)-= x->bf > 0?x->bf:0;
--(x->bf)+= y->bf < 0?y->bf :0;
-------------------------------删除---------------------------
对于插入来说,其实只有在balancefactor的调整上和插入略有不同, 如果删除的节点是左儿子,那么该节点的factor就要减1,如果是右儿子,就要加1.其他关于不满足AVL树时的调整和插入一样的。
------------------------------------------代码---------------------------------------
#include <iostream>
#include <string>
#include <fstream>
#define p y->parent
#define q p?((p->left == y)? p->left : p->right):root
using namespace std;
class Node
{
public:
friend class AVLtree;
Node();
string getdata()
{
return data;
}
void set(int, string);
private:
int key;
string data;
Node *parent;
Node *left;
Node *right;
int factor;
};
class AVLtree
{
public:
AVLtree()
{
root = NULL;
}
Node * get()
{
return root;
}
void insert(int , string );
void deletenode(int );
void preorder(Node *x);
Node * search(int );
Node * successor(int );
Node * leftRotate(Node *);
Node * rightRotate(Node *);
private:
Node* root;
};
AVLtree tree;
ofstream output;
int main()
{
output.open("output.txt");
ifstream input;
input.open("input.txt");
int n;
while(input>>n)
{
int m;
string s;
if(n == 0)
{
if(tree.get() == NULL)
output<<"-1"<<endl;
else
tree.preorder(tree.get());
}
else if(n == 1)
{
input>>m>>s;
tree.insert(m,s);
}
else if(n == 2)
{
input>>m;
tree.deletenode(m);
}
else
{
input>>m;
output<<m<<","<<(tree.search(m))->getdata()<<endl;
}
}
input.close();
output.close();
return 0;
}
Node::Node()
{
parent = NULL;
left = NULL;
right = NULL;
factor = 0;
}
void Node::set(int m,string s )
{
key = m;
data = s;
}
Node* AVLtree::search(int m)
{
Node *temp = new Node;
temp = root;
while(temp != NULL)
{
if(temp->key > m)
temp = temp->left;
else if(temp->key < m)
temp = temp->right;
else
{
return temp;
}
}
}
Node * AVLtree::successor(int m)
{
Node *temp = new Node;
temp = search(m);
if(temp->right != NULL)
{
temp = temp->right;
while(temp->left != NULL)
{
temp = temp->left;
}
return temp;
}
else
{
while(temp->parent!= NULL && temp == (temp->parent)->left)
{
temp = temp->parent;
}
return temp;
}
}
void AVLtree::insert(int m,string s)
{
Node *x = new Node;
x->set(m,s);
Node *temp = new Node;
temp = root;
Node *y = new Node;
y = NULL;
while(temp != NULL)
{
y = temp;
if(temp->key < m)
temp = temp->right;
else if(temp->key > m)
temp = temp->left;
}
if(y == NULL)
root = x;
else
{
x->parent = y;
if(m < y->key)
y->left = x;
else
y->right = x;
}
while(y!= NULL)
{
y->factor += (y->key > m ? 1 : -1);
if(y->factor == -2)
{
if((y->right)->factor == 1)
rightRotate(q->right);
y = leftRotate(q);
}
else if(y->factor == 2)
{
if((y->left)->factor == -1)
leftRotate(q->left);
y = rightRotate(q);
}
if(y->factor == 0)
break;
m = y->key;
y = y->parent;
}
}
Node * AVLtree::leftRotate(Node *x)
{
Node *y = new Node;
y = x->right;
x->right = y->left;
if(y->left != NULL)
(y->left)->parent = x;
y->parent = x->parent;
if(x->parent == NULL)
{
root = y;
}
else if(x == (x->parent)->left)
{
(x->parent)->left = y;
}
else
(x->parent)->right = y;
y->left = x;
x->parent = y;
x->factor -= y->factor < 0 ? y->factor : 0;
(x->factor)++;
y->factor += x->factor > 0? x->factor : 0;
(y->factor)++;
return y;
}
Node * AVLtree::rightRotate(Node *x)
{
Node *y = new Node;
y = x->left;
x->left = y->right;
if(y->right != NULL)
(y->right)->parent = x;
y->parent = x->parent;
if(x->parent == NULL)
root = y;
else if(x == (x->parent)->left)
(x->parent)->left = y;
else
(x->parent)->right = y;
y->right = x;
x->parent = y;
x->factor -= y->factor > 0 ? y->factor : 0;
(x->factor)--;
y->factor += x->factor < 0 ? x->factor : 0;
(y->factor)--;
return y;
}
void AVLtree::preorder(Node *x)
{
if(x == NULL)
return;
else
{
output<<x->key<<","<<x->data<<endl;
preorder(x->left);
preorder(x->right);
}
}
void AVLtree::deletenode(int x)
{
Node *temp = new Node;
Node *z = new Node;
Node *a = new Node;
temp = search(x);
if(temp->left == NULL ||temp->right == NULL)
z = temp;
else
z = successor(x);
if(z->left != NULL)
a = z->left;
else
a = z->right;
if(a != NULL)
a->parent = z->parent;
if(z->parent == NULL)
root = a;
else if(z == z->parent->left)
z->parent->left = a;
else
z->parent->right = a;
if(z->key != temp->key)
{
temp->key = z->key;
temp->data = z->data;
}
Node *y = new Node;
y = z->parent;
int m = z->key;
while(y != NULL)
{
y->factor -= (y->key > m)? 1 : -1;
if(y->factor == -2)
{
Node *temp;
if(y->right->factor == 1)
temp = rightRotate(q->right);
y = leftRotate(q);
}
else if(y->factor == 2)
{
Node *temp;
if(y->left->factor == -1)
temp = leftRotate(q->left);
y = rightRotate(q);
}
if(y->factor == 0)
break;
m = y->key;
y = y->parent;
}
}