高性能流媒体服务器-nebula之数据结构(3)--AVL树定时器

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

    原文作者:AVL树
    原文地址: https://blog.csdn.net/u013265592/article/details/52397762
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞