Implementation of the C-language minimum heap-priority queue __c language

Source: Internet
Author: User
I. Background

Libevent in the management of timed events, users can be timed to the timing of the event into the manager, when the time to trigger the user's callback function processing;

Check the source found that the timer data structure is actually by the smallest heap to achieve. Ii. Relevant Knowledge 2.1 Minimum Heap (minimum priority queue) The priority queue (priority) is a data structure used to maintain the set S of a set of elements "--an introduction to the algorithm P90 according to the simple can be understood as using an array of two-fork tree, and satisfy each child node key value is greater than the parent node key value; The following code is modified based on libevent-2.0.20-stable/minheap-internal.h, which improves some readability;

static inline void Min_heap_ctor (min_heap_t * pheap);
static inline void Min_heap_dtor (min_heap_t * pheap);
static inline void Min_heap_elem_init (struct event *e);
static inline int min_heap_elt_is_top (const struct event *e);
static inline int Min_heap_elem_greater (struct event *max_size, struct event *b);
static inline int Min_heap_empty (min_heap_t * pheap);
Static inline unsigned min_heap_size (min_heap_t * pheap);
Static inline struct event * min_heap_top (min_heap_t * pheap);
static inline int __reserve (min_heap_t * pheap, unsigned used_num);
static inline int Min_heap_push (min_heap_t * pheap, struct event *e);
Static inline struct event * MIN_HEAP_POP (min_heap_t * pheap);
static inline int min_heap_erase (min_heap_t * pheap, struct event *e);
static inline void __shift_up (min_heap_t * pheap, unsigned hole_idx, struct event *e); static inline void __shift_down (min_heap_t * pheap, unsigned hole_idx, struct EVent *e); 

The data structure is as follows, the original struct event actually corresponds to the context of the incident, where some simplification is made;
struct Event {
    u32 idx;        /* Node index *

    /int key;        * Custom key *
    /void *pdata;    /* Custom data *
/};

typedef struct MIN_HEAP
{
    struct event **p;
    U32 Used_num;
    U32 max_size;
} min_heap_t;

#define __KEY_CMP (A, B) ((a)->key > (b)->key)
#define __get_parent (IDX) ((IDX)-1)/2)
#define __get _child_left (IDX) (2 * (IDX) + 1))
Related operation macros, then filter (push operation), down filter operation (pop operation)
static void __shift_up (min_heap_t *pheap, u32 hole_idx, struct event *e) {u32 parent = __get_parent (HOLE_IDX);
        while (Hole_idx && __key_cmp (pheap->p[parent], E)) {Pheap->p[hole_idx] = pheap->p[parent];

        Pheap->p[hole_idx]->idx = Hole_idx;
        Hole_idx = parent;
    Parent = __get_parent (HOLE_IDX);
    } Pheap->p[hole_idx] = e;
Pheap->p[hole_idx]->idx = Hole_idx;

    } static void __shift_down (min_heap_t * pheap, u32 hole_idx, struct event *e) {u32 Min_child = 2 * (HOLE_IDX + 1);
                while (Min_child <= pheap->used_num) {#if 1 if (min_child = = Pheap->used_num | |
        __KEY_CMP (Pheap->p[min_child], pheap->p[min_child-1])) {min_child--; } #else Min_child-= Min_child = = Used_num | |
__KEY_CMP (Pheap->p[min_child], pheap->p[min_child-1]); #endif if (!) (
        __KEY_CMP (E, pheap->p[min_child])) {break;
   }     (Pheap->p[hole_idx] = Pheap->p[min_child])->idx = HOLE_IDX;
        Hole_idx = Min_child;
    Min_child = 2 * (HOLE_IDX + 1);
} (Pheap->p[hole_idx] = e)->idx = Hole_idx;
 }

For the maintenance of the array, the logic inside realizes the first 8 space, when the new space is not enough time, and then doubled expansion;
static int __reserve (min_heap_t *pheap, u32 expect)
{
    if (Pheap->max_size < expect) {
        struct event **p ;
        U32 max_size = pheap->max_size? Pheap->max_size * 2:8;
        if (Max_size < expect) {
            max_size = expect;
        }

        p = (struct event * *) realloc (pheap->p, max_size * sizeof (*P));
        if (!p) {return
            failure;
        }

        Pheap->p = p;
        Pheap->max_size = max_size;
    }
    return SUCCESS;
}

The preparation work is done, then the push operation, by inserting the element at the end of the array, then filtering and adjusting; the pop operation is to remove the top (minimum) and then filter the structure of the stack;
int Min_heap_push (min_heap_t *pheap, int key, void *pdata)
{
    if (__reserve (pheap, Pheap->used_num + 1)) {
  
   return failure;
    }

    struct Event *e = (struct event *) calloc (1, sizeof (struct event));
    if (!e) {return
        failure;
    }

    E->key = key;
    E->pdata = pdata;

    __shift_up (Pheap, pheap->used_num++, e);
    return SUCCESS;
}

  

void *min_heap_pop (min_heap_t *pheap)
{
    void *pdata = NULL;

    if (!pheap | |!pheap->used_num) {
        LOGW ("NULL or empty\n");
        return NULL;
    }

    struct Event *e = *pheap->p;

    __shift_down (Pheap, 0u, Pheap->p[--pheap->used_num]);
    E->idx =-1;
    pdata = e->pdata;

    Free_pointer (e);
    return pdata;
}

Finally, attach a simple test, and finally construct the effect for the previous chapter of the structure diagram;
int __on_traverse (void *args, int key, void *pdata) {printf ("%d%d\n", Key, * (char *) pdata);
return SUCCESS;
    int main (int argc, char *argv[]) {int ret = failure;
    
    int IX = 0;
    int *c = NULL;
        struct Test {int key;
    int value; 
        } test[] = {3, 3}, {14, 14}, {7, 7}, {15, 15}, {8, 8}, {2, 2},  

    {9, 9}, {10, 10}, {16, 16},};

    min_heap_t heap = {0}; for (ix = 0; IX < sizeof (test)/sizeof (struct test); ix++) {ASSERT (SUCCESS, ret = Min_heap_push (&heap, t
    Est[ix].key, &test[ix].value)); for (ix = 0; IX < sizeof (test)/sizeof (struct test); ix++) {Assert_fail (NULL, C = Min_heap_pop (&am P;HEAP));
    printf ("%d\n", *c);
    ret = SUCCESS;
Goto _e1; _e1:printf ("result:\t\t\t\t[%s]\n", ret?)
    "Failure": "Success"); Exit (ret?)
exit_failure:exit_success); }

Iv. SummaryPriority teams are listed as complete binary trees, therefore, the time complexity of the insertion adjustment is O (N), the popup complexity is O (1), but for the characteristics of the priority queue, the search and delete operations will be more troublesome; look closely at the Libevent miniheap inside also has the deletion interface, is given struct The location of the event to delete, the original is libevent internal also combined with the red-black tree, linked list for struct event maintenance, so reasonable;


Reference article: [1] About source analysis http://www.cnblogs.com/sdu20112013/p/4104439.html [2] About time complexity http://blog.csdn.net/don_lvsml/ article/details/19546997


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.