AVL树在nebula中的使用场景主要用于定时器的管理,对于线性增长的timestamp,经我们测试,AVL树比红黑数定时器在性能方面有一定的优势,尤其在WINDOWS平台表现得特别突出,所以我们采用AVL树作为nebula的定时器管理,下面是具体实现:
//
// avltree.h
// nebula
//
// Created by yi.cheng on 16/5/7.
// Copyright © 2016 kanshansoft. All rights reserved.
//
#ifndef avltree_h
#define avltree_h
/* no parent pointer */
template struct AVLNode{
K key;
int balance;
struct AVLNode* l;
struct AVLNode* r;
struct AVLNode* p;
inline AVLNode() : l(NULL), r(NULL), p(NULL), balance(0) {}
};
template class AVLTree {
AVLTree(const AVLTree&);
AVLTree& operator = (const AVLTree&);
public:
AVLTree();
int insert(AVLNode* node);
void remove(AVLNode* node);
AVLNode* find(const K& key);
AVLNode* find_min();
inline bool empty() const {
return root == NULL;
}
private:
AVLNode* root;
};
template AVLTree::AVLTree() : root(NULL) {}
template int AVLTree::insert(AVLNode* node)
{
AVLNode *parent = nullptr; //this ensures the parent of the root node is NULL;
AVLNode **n = &root;
node->l = node->r = node->p = nullptr;
node->balance = 0;
while ((*n)) {
parent = *n;
if(parent->key < node->key)
n = &parent->r;
else if(node->key < parent->key)
n = &parent->l;
else
return -1;
}
*n = node;
node->p = parent;
avl_fixup_insert(root, node);
return 0;
}
template AVLNode* AVLTree::find(const K& key)
{
auto p = root;
while(p){
auto item = p;
if(item->key < key)
p = p->r;
else if(key < item->key)
p = p->l;
else
return item;
}
return nullptr;
}
template inline AVLNode* AVLTree::find_min()
{
AVLNode* p = root;
while(p->l){
p = p->l;
}
return p;
}
template inline void AVLTree::remove(AVLNode* node)
{
avl_del_node(root, node);
}
#include
#endif /* avltree_h */
//
// avltree.cpp
// nebula
//
// Created by yi.cheng on 16/5/7.
// Copyright © 2016 kanshansoft. All rights reserved.
//
#include
#include
template void __left_rotate(AVLNode *n, AVLNode *&root)
{
AVLNode *parent = n->p;
AVLNode *right = n->r;
if ((n->r = right->l))
n->r->p = n;
n->p = right;
right->l = n;
right->p = parent;
if (parent) {
if (parent->l == n)
parent->l = right;
else
parent->r = right;
} else
root = right;
}
template void __right_rotate(AVLNode *n, AVLNode *&root)
{
AVLNode *parent = n->p;
AVLNode *left = n->l;
if ((n->l = left->r))
n->l->p = n;
n->p = left;
left->r = n;
left->p = parent;
if (parent) {
if (parent->l == n)
parent->l = left;
else
parent->r = left;
} else
root = left;
}
template inline void avl_lr_rotate(AVLNode *parent, AVLNode *&r)
{
__left_rotate(parent->l, r);
__right_rotate(parent, r);
}
template inline void avl_rl_rotate(AVLNode *parent, AVLNode *&r)
{
__right_rotate(parent->r, r);
__left_rotate(parent, r);
}
template void avl_fixup_insert(AVLNode *&r, AVLNode *x)
{
AVLNode *parent;
AVLNode *child;
for(; (parent = x->p); x = parent){
if (parent->l == x) {
parent->balance++;
if (parent->balance == 0)
break;
if (parent->balance == 1)
continue;
//rotate
if (x->balance == 1) { //LL
x->balance = 0;
parent->balance = 0;
__right_rotate(parent, r);
break;
}
//LR, x->balance == -1
child = x->r;
parent->balance = x->balance = 0;
if (child->balance == 1)
parent->balance = -1;
else if (child->balance == -1)
x->balance = 1;
child->balance = 0;
avl_lr_rotate(parent, r);
break;
} else {
parent->balance--;
if (parent->balance == 0)
break;
if (parent->balance == -1)
continue;
//rotate
//assert(parent->balance == -2);
if (x->balance == -1) {
x->balance = parent->balance = 0;
__left_rotate(parent, r);
break;
}
//RL, x->balance = 1
child = x->l;
parent->balance = x->balance = 0;
if (child->balance == -1)
parent->balance = 1;
else if (child->balance == 1)
x->balance = -1;
child->balance = 0;
avl_rl_rotate(parent, r);
break;
}
}
}
// x's balance is to be decreased
// left == true child is left, left == false, child is right
template void avl_fixup_del(AVLNode *&r, AVLNode *x, bool left)
{
AVLNode *parent;
AVLNode *child;
AVLNode *gc;
for(;x;x=parent){
parent = x->p;
if (left) {
x->balance--;
if (x->balance == -1)
break;
if (parent && parent->r == x)
left = false;
if (x->balance == 0)
continue;
// x's balance is -1, now to be -2, so should rotate.
child = x->r;
//assert(x->balance == -2 && child);
if (child->balance == 0) {
x->balance = -1;
child->balance = 1;
__left_rotate(x, r);
break;
}
if (child->balance == -1) {
x->balance = child->balance = 0;
__left_rotate(x, r);
continue;
}
gc = child->l;
//child 's balance == 1
//assert(child->balance == 1 && gc);
x->balance = child->balance = 0;
if(gc->balance == -1)
x->balance = 1;
else if(gc->balance == 1)
child->balance = -1;
gc->balance = 0;
avl_rl_rotate(x, r);
} else {
x->balance++;
if (x->balance == 1)
break;
if (parent && parent->l == x)
left = true;
if (x->balance == 0)
continue;
child = x->l;
//assert(x->balance == 2 && child);
if (child->balance == 0) {
x->balance = 1;
child->balance = -1;
__right_rotate(x, r);
break;
}
if (child->balance == 1) {
x->balance = child->balance = 0;
__right_rotate(x, r);
continue;
}
gc = child->r;
//assert(child->balance == -1 && gc);
x->balance = child->balance = 0;
if(gc->balance == 1)
x->balance = -1;
else if(gc->balance == -1)
child->balance = 1;
gc->balance = 0;
avl_lr_rotate(x, r);
}
}
}
template void avl_del_node(AVLNode *&r, AVLNode *n)
{
AVLNode *parent;
AVLNode *child;
AVLNode *target;
bool left = false;
target = parent = n->p;
if (!n->l)
child = n->r;
else if (!n->r)
child = n->l;
else {
//both n->l and n->r are not nil
AVLNode *x = n->r;
AVLNode *xp;
while (x->l)
x = x->l;
child = x->r;
xp = x->p;
if (parent) {
if (parent->l == n)
parent->l = x;
else
parent->r = x;
} else
r = x;
x->p = parent; //
x->l = n->l;
n->l->p = x;
x->balance = n->balance;
if (xp != n) { //n->r has no left child
if (child)
child->p = xp;
xp->l = child;
x->r = n->r;
n->r->p = x;
target = xp;
left=true;
} else{
target = x;
left = false;
}
goto fixup;
}
if (parent) {
if (parent->l == n) {
parent->l = child;
left = true;
} else {
parent->r = child;
left = false;
}
} else
r = child;
if (child)
child->p = parent;
fixup:
if (r)
avl_fixup_del(r, target, left);
n->p = n->l = n->r = NULL;
}