高性能流媒体服务器-nebula之数据结构(2)--pairing heap

pairing heap在nebula studio中的使用场景主要用于HLS流和UDP流的限速发送,pairing heap用于timed queue的底层实现,在我们的pairing heap的中,实现了两种pairing heap,一个分配节点内存,一个不分配节点内存,据测试,比STL中的优先队列性能高出近1倍,下面是具体实现:

//
//  pairingheap.h
//  nebula
//
//  Created by yi.cheng on 16/4/28.
//  Copyright © 2016 kanshansoft. All rights reserved.
//

#ifndef pairingheap_h
#define pairingheap_h
#include 
   
   
    
    
#include 
    
    
     
     

namespace anysee {
    //! Pairing heap node.
    template
     
     
      
      
    struct PairingHeapNode {

        T value; //!< Value contained in the node.
        
        PairingHeapNode
      
      
       
        *prev; //!< Previous sibling of the node or parent.
        PairingHeapNode
       
       
         *next; //!< Next sibling of the node. PairingHeapNode 
        
          *child; //!< First child of the node. //! Creates heap node with a given \a value. inline PairingHeapNode(const T &val) : value(val), prev(nullptr), next(nullptr), child(nullptr) { } inline PairingHeapNode(T&& val) : value(std::move(val)), prev(nullptr), next(nullptr), child(nullptr) { } }; //! Pairing heap implementation. /** * @ingroup containers * * Code is mainly based on orginal paper "The Pairing Heap: A New Form of * Self-Adjusting Heap" by Fredman, Sedgewick, Sleator and Tarjan. * * @tparam T Denotes value type of inserted elements. * @tparam C Denotes comparison functor determining value ordering. */ template 
         
           > class PairingHeap { public: /** * Creates empty pairing heap. * * @param cmp Comparison functor determining value ordering. * @param initialSize ignored by this implementation. */ PairingHeap(const C &cmp = C(), int initialSize = -1); /** * Destructs pairing heap. * * If the heap is not empty, destructors of contained elements are called * and used storage is deallocated. */ virtual ~PairingHeap(); //! Returns reference to the top element in the heap. const T &top() const; /** * Inserts a new node with given \a value into a heap. * * @param value A value to be inserted. * @return Handle to the inserted node. */ PairingHeapNode 
          
            *push(const T &value); PairingHeapNode 
           
             *push(const T &value, bool& isHeadChanged); PairingHeapNode 
            
              *push(T &&value); PairingHeapNode 
             
               *push(T &&value, bool& isHeadChanged); /** * Removes the top element from the heap. * * Behaviour of this function is undefined if the heap is empty. */ T pop(); /** * Decreases value of the given \a node to \a value. * * Behaviour of this function is undefined if node does not belong to a the * heap or new value is greater than old one. * * @param node A node for which the value is to be decreased. * @param value A new value for the node. */ void decrease(PairingHeapNode 
              
                *node, const T &value); /** * Merges in values of \a other heap. * * After merge \a other heap becomes empty and is valid for further usage. * * @param other A heap to be merged in. */ void merge(PairingHeap 
               
                 &other); /* * Retuns the value of the node * * @param node The nodes handle * @return the value of the node */ const T &value(PairingHeapNode 
                
                  *node) const { return node->value; } inline bool isEmpty() const { return (m_root == NULL); } private: C m_comp; ObjPool 
                  
                  
                    > m_pool; PairingHeapNode 
                   
                     *m_root; //!< Root node of the heap. //! Pairs list of heaps given as \a node. Returns resulting list. PairingHeapNode 
                    
                      *pair(PairingHeapNode 
                     
                       **node); //! Merges lists of heaps \a a and \a b. Returns resulting list. PairingHeapNode 
                      
                        *merge(PairingHeapNode 
                       
                         *a, PairingHeapNode 
                        
                          *b); //! Makes \a child node a child of \a parent node. void link(PairingHeapNode 
                         
                           *parent, PairingHeapNode 
                          
                            *child); //! Removes \a node from its parent children list. void unlink(PairingHeapNode 
                           
                             *node); //! Releases memory occupied by list of heaps given as \a node. void release(PairingHeapNode 
                            
                              *node); }; template 
                             
                               PairingHeap 
                              
                                ::PairingHeap(const C &cmp, int initialSize) : m_root(nullptr), m_pool(1024) { this->m_comp = cmp; } template 
                               
                                 PairingHeap 
                                
                                  ::~PairingHeap() { release(m_root); m_root = nullptr; } template 
                                 
                                   inline const T &PairingHeap 
                                  
                                    ::top() const { return m_root->value; } template 
                                   
                                     inline PairingHeapNode 
                                    
                                      *PairingHeap 
                                     
                                       ::push(const T &value, bool& isHeadChanged) { PairingHeapNode 
                                      
                                        *node = m_pool.alloc(value); PairingHeapNode 
                                       
                                         *root = m_root; m_root = m_root == nullptr ? node : merge(m_root, node); isHeadChanged = (root == m_root) ? false : true; return node; } template 
                                        
                                          inline PairingHeapNode 
                                         
                                           *PairingHeap 
                                          
                                            ::push(const T &value) { PairingHeapNode 
                                           
                                             *node = m_pool.alloc(value); m_root = m_root == nullptr ? node : merge(m_root, node); return node; } template 
                                            
                                              inline PairingHeapNode 
                                             
                                               *PairingHeap 
                                              
                                                ::push(T && value, bool& isHeadChanged) { PairingHeapNode 
                                               
                                                 *node = m_pool.alloc(std::move(value)); PairingHeapNode 
                                                
                                                  *root = m_root; m_root = m_root == nullptr ? node : merge(m_root, node); isHeadChanged = (root == m_root) ? false : true; return node; } template 
                                                 
                                                   inline PairingHeapNode 
                                                  
                                                    *PairingHeap 
                                                   
                                                     ::push(T && value) { PairingHeapNode 
                                                    
                                                      *node = m_pool.alloc(std::move(value)); m_root = m_root == nullptr ? node : merge(m_root, node); return node; } template 
                                                     
                                                       inline T PairingHeap 
                                                      
                                                        ::pop() { PairingHeapNode 
                                                       
                                                         *children = m_root->child; T val = m_root->value; m_pool.free(m_root); m_root = pair(&children); return val; } template 
                                                        
                                                          void PairingHeap 
                                                         
                                                           ::decrease(PairingHeapNode 
                                                          
                                                            *node, const T &value) { node->value = value; unlink(node); if (node->child) node = merge(node, pair(&node->child)); if (node != m_root) { if (m_root != NULL) m_root = merge(m_root, node); else m_root = node; } } template 
                                                           
                                                             void PairingHeap 
                                                            
                                                              ::merge(PairingHeap 
                                                             
                                                               &other) { m_root = merge(m_root, other.m_root); other.m_root = nullptr; } template 
                                                              
                                                                inline PairingHeapNode 
                                                               
                                                                 *PairingHeap 
                                                                
                                                                  ::pair( PairingHeapNode 
                                                                 
                                                                   **node) { if(*node == nullptr) { return nullptr; } PairingHeapNode 
                                                                  
                                                                    * first_child = *node; PairingHeapNode 
                                                                   
                                                                     * second_child = (*node)->next; PairingHeapNode 
                                                                    
                                                                      * merge_node = NULL; first_child->prev = first_child->next = NULL; if(second_child == NULL) { merge_node = first_child; return merge_node; } else { *node = second_child->next; second_child->prev = second_child->next = NULL; merge_node = merge(first_child, second_child); } PairingHeapNode 
                                                                     
                                                                       * node_list = merge_node; PairingHeapNode 
                                                                      
                                                                        * cur_node_list = node_list; while (*node) { first_child = *node; second_child = (*node)->next; first_child->prev = first_child->next = NULL; if(second_child == NULL) { merge_node = first_child; *node = (*node)->next; } else { *node = second_child->next; second_child->prev = second_child->next = NULL; merge_node = merge(first_child, second_child); } cur_node_list->next = merge_node; merge_node->prev = cur_node_list; cur_node_list = merge_node; } merge_node = pair(&node_list); return merge_node; } template 
                                                                       
                                                                         inline PairingHeapNode 
                                                                        
                                                                          *PairingHeap 
                                                                         
                                                                           ::merge( PairingHeapNode 
                                                                          
                                                                            *a, PairingHeapNode 
                                                                           
                                                                             *b) { if(nba_likely(this->m_comp(a->value, b->value))) { link(a, b); return a; } else { link(b, a); return b; } } template 
                                                                            
                                                                              inline void PairingHeap 
                                                                             
                                                                               ::link( PairingHeapNode 
                                                                              
                                                                                *root, PairingHeapNode 
                                                                               
                                                                                 *child) { if(root->child != nullptr) { child->next = root->child; root->child->prev = child; } child->prev = root; root->child = child; } template 
                                                                                
                                                                                  inline void PairingHeap 
                                                                                 
                                                                                   ::unlink( PairingHeapNode 
                                                                                  
                                                                                    *node) { if(node->prev) { if(node->prev->child == node) { node->prev->child = node->next; } else { node->prev->next = node->next; } } if(node->next != nullptr) { node->next->prev = node->prev; } node->prev = nullptr; node->next = nullptr; } template 
                                                                                   
                                                                                     inline void PairingHeap 
                                                                                    
                                                                                      ::release(PairingHeapNode 
                                                                                     
                                                                                       *node) { /* * Recursive version of this function is infinitely prettier than that * abomination. Please, make it prettier if you can. */ PairingHeapNode 
                                                                                      
                                                                                        *it = node; if(it == nullptr) { return; } for(;;) { // Slide down as long as possible. if(it->child != nullptr) { it = it->child; continue; } if(it->next != nullptr) { it = it->next; continue; } // Climb up until you find first non-visited node. for(;;) { PairingHeapNode 
                                                                                       
                                                                                         *curr = it, *prev = it->prev; m_pool.free(it); if(prev == nullptr) { return; } if(curr == prev->child && prev->next != nullptr) { it = prev->next; break; } else { it = prev; } } } } template 
                                                                                        
                                                                                          > class PairingNeutralHeap { public: struct PairTreeNode { inline PairTreeNode() : prev(nullptr), next(nullptr), child(nullptr) { } PairTreeNode *prev; //!< Previous sibling of the node or parent. PairTreeNode *next; //!< Next sibling of the node. PairTreeNode *child; //!< First child of the node. K key; //key }; /** * Creates empty pairing heap. * * @param cmp Comparison functor determining value ordering. * @param initialSize ignored by this implementation. */ PairingNeutralHeap(const C &cmp = C(), int initialSize = -1); /** * Destructs pairing heap. * * If the heap is not empty, destructors of contained elements are called * and used storage is deallocated. */ virtual ~PairingNeutralHeap(); //! Returns reference to the top element in the heap. const PairTreeNode* top() const; /** * Inserts a new node with given \a value into a heap. * * @param value A value to be inserted. * @return Handle to the inserted node. */ void push(PairTreeNode* node, bool& isHeadChanged); /** * Removes the top element from the heap. * * Behaviour of this function is undefined if the heap is empty. */ PairTreeNode* pop(); /** * Decreases value of the given \a node to \a value. * * Behaviour of this function is undefined if node does not belong to a the * heap or new value is greater than old one. * * @param node A node for which the value is to be decreased. * @param value A new value for the node. */ void decrease(PairTreeNode *node); /** * Merges in values of \a other heap. * * After merge \a other heap becomes empty and is valid for further usage. * * @param other A heap to be merged in. */ void merge(PairingNeutralHeap 
                                                                                         
                                                                                           &other); inline bool isEmpty() const { return (m_root == NULL); } private: C m_comp; PairTreeNode *m_root; //!< Root node of the heap. //! Pairs list of heaps given as \a node. Returns resulting list. PairTreeNode *pair(PairTreeNode **node); //! Merges lists of heaps \a a and \a b. Returns resulting list. PairTreeNode *merge(PairTreeNode *a, PairTreeNode *b); //! Makes \a child node a child of \a parent node. void link(PairTreeNode *parent, PairTreeNode *child); //! Removes \a node from its parent children list. void unlink(PairTreeNode *node); void swap(PairTreeNode *a, PairTreeNode* b); //! Releases memory occupied by list of heaps given as \a node. void release(PairTreeNode *node); }; template 
                                                                                          
                                                                                            PairingNeutralHeap 
                                                                                           
                                                                                             ::PairingNeutralHeap(const C &cmp, int initialSize) : m_root(nullptr) { this->m_comp = cmp; } template 
                                                                                            
                                                                                              PairingNeutralHeap 
                                                                                             
                                                                                               ::~PairingNeutralHeap() { release(m_root); m_root = nullptr; } template 
                                                                                              
                                                                                                inline const typename PairingNeutralHeap 
                                                                                               
                                                                                                 ::PairTreeNode* PairingNeutralHeap 
                                                                                                
                                                                                                  ::top() const { return m_root; } template 
                                                                                                 
                                                                                                   inline void PairingNeutralHeap 
                                                                                                  
                                                                                                    ::push(PairTreeNode* node, bool& isHeadChanged) { PairTreeNode* root = m_root; m_root = m_root == nullptr ? node : merge(m_root, node); isHeadChanged = (m_root == root) ? false : true; } /** * \b Effects: Removes top element from the priority_queue. * * \cond * \b Complexity: \f$2^2log(log(N))\f$ (amortized). * \endcond * * \b Complexity: 2**2*log(log(N)) (amortized). * */ template 
                                                                                                   
                                                                                                     typename PairingNeutralHeap 
                                                                                                    
                                                                                                      ::PairTreeNode* PairingNeutralHeap 
                                                                                                     
                                                                                                       ::pop() { PairTreeNode* node = m_root; PairTreeNode *children = m_root->child; m_root = pair(&children); return node; } /** * \b Effects: decrease the heap after the element has been changed. * * \cond * \b Complexity: \f$2^2log(log(N))\f$ (amortized). * \endcond * * \b Complexity: 2**2*log(log(N)) (amortized). * * \b Note: If this is not called, after a handle has been updated, the behavior of the data structure is undefined! * */ template 
                                                                                                      
                                                                                                        void PairingNeutralHeap 
                                                                                                       
                                                                                                         ::decrease(PairTreeNode *node) { unlink(node); if (node->child) node = merge(node, pair(&node->child)); if (node != m_root) { if (m_root != NULL) m_root = merge(m_root, node); else m_root = node; } } template 
                                                                                                        
                                                                                                          void PairingNeutralHeap 
                                                                                                         
                                                                                                           ::merge(PairingNeutralHeap 
                                                                                                          
                                                                                                            &other) { m_root = merge(m_root, other.m_root); other.m_root = nullptr; } template 
                                                                                                           
                                                                                                             inline typename PairingNeutralHeap 
                                                                                                            
                                                                                                              ::PairTreeNode *PairingNeutralHeap 
                                                                                                             
                                                                                                               ::pair( PairTreeNode **node) { if(*node == nullptr) { return nullptr; } PairTreeNode* first_child = *node; PairTreeNode* second_child = (*node)->next; PairTreeNode* merge_node = NULL; first_child->prev = first_child->next = NULL; if(second_child == NULL) { merge_node = first_child; return merge_node; } else { *node = second_child->next; second_child->prev = second_child->next = NULL; merge_node = merge(first_child, second_child); } PairTreeNode* node_list = merge_node; PairTreeNode* cur_node_list = node_list; while (*node) { first_child = *node; second_child = (*node)->next; first_child->next = first_child->prev = NULL; if(second_child == NULL) { merge_node = first_child; *node = (*node)->next; } else { *node = second_child->next; second_child->prev = second_child->next = NULL; merge_node = merge(first_child, second_child); } cur_node_list->next = merge_node; merge_node->prev = cur_node_list; cur_node_list = merge_node; } merge_node = pair(&node_list); return merge_node; } template 
                                                                                                              
                                                                                                                inline typename PairingNeutralHeap 
                                                                                                               
                                                                                                                 ::PairTreeNode *PairingNeutralHeap 
                                                                                                                
                                                                                                                  ::merge( PairTreeNode *a, PairTreeNode *b) { if(this->m_comp(a->key, b->key)) { link(a, b); return a; } else { link(b, a); return b; } } template 
                                                                                                                 
                                                                                                                   inline void PairingNeutralHeap 
                                                                                                                  
                                                                                                                    ::swap(PairTreeNode *a, PairTreeNode* b) { PairTreeNode* c = a; a = b; b = c; } template 
                                                                                                                   
                                                                                                                     inline void PairingNeutralHeap 
                                                                                                                    
                                                                                                                      ::link( PairTreeNode *root, PairTreeNode *child) { if(root->child != nullptr) { child->next = root->child; root->child->prev = child; } child->prev = root; root->child = child; } template 
                                                                                                                     
                                                                                                                       inline void PairingNeutralHeap 
                                                                                                                      
                                                                                                                        ::unlink( PairTreeNode *node) { if(node->prev != NULL) { if(node->prev->child == node) { node->prev->child = node->next; } else { node->prev->next = node->next; } } if(node->next != nullptr) { node->next->prev = node->prev; } node->prev = nullptr; node->next = nullptr; } template 
                                                                                                                       
                                                                                                                         inline void PairingNeutralHeap 
                                                                                                                        
                                                                                                                          ::release(PairTreeNode *node) { /* * Recursive version of this function is infinitely prettier than that * abomination. Please, make it prettier if you can. */ PairTreeNode *it = node; if(it == nullptr) { return; } for(;;) { // Slide down as long as possible. if(it->child != nullptr) { it = it->child; continue; } if(it->next != nullptr) { it = it->next; continue; } // Climb up until you find first non-visited node. for(;;) { PairTreeNode *curr = it, *prev = it->prev; if(prev == nullptr) { return; } if(curr == prev->child && prev->next != nullptr) { it = prev->next; break; } else { it = prev; } } } } } #endif /* pairingheap_h */ 
                                                                                                                         

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值