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; }