2012-01-24 15:07:41 -08:00
|
|
|
|
/*
|
2013-07-22 09:19:57 -07:00
|
|
|
|
* Copyright (c) 2012, 2013 Nicira, Inc.
|
2012-01-24 15:07:41 -08:00
|
|
|
|
*
|
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
|
* You may obtain a copy of the License at:
|
|
|
|
|
*
|
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
*
|
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
|
* limitations under the License.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifndef HEAP_H
|
|
|
|
|
#define HEAP_H 1
|
|
|
|
|
|
|
|
|
|
#include <stdbool.h>
|
|
|
|
|
#include <stddef.h>
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
|
|
|
|
|
/* A heap node, to be embedded inside the data structure in the heap. */
|
|
|
|
|
struct heap_node {
|
|
|
|
|
size_t idx;
|
2013-10-16 03:32:31 +00:00
|
|
|
|
uint64_t priority;
|
2012-01-24 15:07:41 -08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* A max-heap. */
|
|
|
|
|
struct heap {
|
|
|
|
|
struct heap_node **array; /* Data in elements 1...n, element 0 unused. */
|
|
|
|
|
size_t n; /* Number of nodes currently in the heap. */
|
|
|
|
|
size_t allocated; /* Max 'n' before 'array' must be enlarged. */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Initialization. */
|
|
|
|
|
void heap_init(struct heap *);
|
|
|
|
|
void heap_destroy(struct heap *);
|
|
|
|
|
void heap_clear(struct heap *);
|
|
|
|
|
void heap_swap(struct heap *a, struct heap *b);
|
|
|
|
|
static inline size_t heap_count(const struct heap *);
|
|
|
|
|
static inline bool heap_is_empty(const struct heap *);
|
|
|
|
|
|
|
|
|
|
/* Insertion and deletion. */
|
2013-10-16 03:32:31 +00:00
|
|
|
|
void heap_insert(struct heap *, struct heap_node *, uint64_t priority);
|
|
|
|
|
void heap_change(struct heap *, struct heap_node *, uint64_t priority);
|
2012-01-24 15:07:41 -08:00
|
|
|
|
void heap_remove(struct heap *, struct heap_node *);
|
|
|
|
|
static inline struct heap_node *heap_pop(struct heap *);
|
|
|
|
|
|
|
|
|
|
/* Maximum. */
|
|
|
|
|
static inline struct heap_node *heap_max(const struct heap *);
|
|
|
|
|
|
|
|
|
|
/* The "raw" functions below do not preserve the heap invariants. After you
|
|
|
|
|
* call them, heap_max() will not necessarily return the right value until you
|
|
|
|
|
* subsequently call heap_rebuild(). */
|
2013-10-16 03:32:31 +00:00
|
|
|
|
void heap_raw_insert(struct heap *, struct heap_node *, uint64_t priority);
|
|
|
|
|
static inline void heap_raw_change(struct heap_node *, uint64_t priority);
|
2012-01-24 15:07:41 -08:00
|
|
|
|
void heap_raw_remove(struct heap *, struct heap_node *);
|
|
|
|
|
void heap_rebuild(struct heap *);
|
|
|
|
|
|
|
|
|
|
/* Iterates through each NODE in HEAP, where NODE->MEMBER must be a "struct
|
|
|
|
|
* heap_node". Iterates in heap level order, which in particular means that
|
|
|
|
|
* the first node visited is the maximum value in the heap.
|
|
|
|
|
*
|
|
|
|
|
* If a heap_raw_*() function has been called without a later call to
|
|
|
|
|
* heap_rebuild(), then the first node visited may not be the maximum
|
|
|
|
|
* element. */
|
|
|
|
|
#define HEAP_FOR_EACH(NODE, MEMBER, HEAP) \
|
|
|
|
|
for (((HEAP)->n > 0 \
|
2014-09-09 14:23:07 -07:00
|
|
|
|
? INIT_CONTAINER(NODE, (HEAP)->array[1], MEMBER) \
|
2013-07-22 09:19:57 -07:00
|
|
|
|
: ((NODE) = NULL, (void) 0)); \
|
2012-01-24 15:07:41 -08:00
|
|
|
|
(NODE) != NULL; \
|
|
|
|
|
((NODE)->MEMBER.idx < (HEAP)->n \
|
|
|
|
|
? ASSIGN_CONTAINER(NODE, \
|
|
|
|
|
(HEAP)->array[(NODE)->MEMBER.idx + 1], \
|
|
|
|
|
MEMBER) \
|
2013-07-22 09:19:57 -07:00
|
|
|
|
: ((NODE) = NULL, (void) 0)))
|
2012-01-24 15:07:41 -08:00
|
|
|
|
|
|
|
|
|
/* Returns the index of the node that is the parent of the node with the given
|
|
|
|
|
* 'idx' within a heap. */
|
|
|
|
|
static inline size_t
|
|
|
|
|
heap_parent__(size_t idx)
|
|
|
|
|
{
|
|
|
|
|
return idx / 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Returns the index of the node that is the left child of the node with the
|
|
|
|
|
* given 'idx' within a heap. */
|
|
|
|
|
static inline size_t
|
|
|
|
|
heap_left__(size_t idx)
|
|
|
|
|
{
|
|
|
|
|
return idx * 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Returns the index of the node that is the right child of the node with the
|
|
|
|
|
* given 'idx' within a heap. */
|
|
|
|
|
static inline size_t
|
|
|
|
|
heap_right__(size_t idx)
|
|
|
|
|
{
|
|
|
|
|
return idx * 2 + 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Returns true if 'idx' is the index of a leaf node in 'heap', false
|
|
|
|
|
* otherwise. */
|
|
|
|
|
static inline bool
|
|
|
|
|
heap_is_leaf__(const struct heap *heap, size_t idx)
|
|
|
|
|
{
|
|
|
|
|
return heap_left__(idx) > heap->n;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Returns the number of elements in 'heap'. */
|
|
|
|
|
static inline size_t
|
|
|
|
|
heap_count(const struct heap *heap)
|
|
|
|
|
{
|
|
|
|
|
return heap->n;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Returns true if 'heap' is empty, false if it contains at least one
|
|
|
|
|
* element. */
|
|
|
|
|
static inline bool
|
|
|
|
|
heap_is_empty(const struct heap *heap)
|
|
|
|
|
{
|
|
|
|
|
return heap->n == 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Returns the largest element in 'heap'.
|
|
|
|
|
*
|
|
|
|
|
* The caller must ensure that 'heap' contains at least one element.
|
|
|
|
|
*
|
|
|
|
|
* The return value may be wrong (i.e. not the maximum element but some other
|
|
|
|
|
* element) if a heap_raw_*() function has been called without a later call to
|
|
|
|
|
* heap_rebuild(). */
|
|
|
|
|
static inline struct heap_node *
|
|
|
|
|
heap_max(const struct heap *heap)
|
|
|
|
|
{
|
|
|
|
|
return heap->array[1];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Removes an arbitrary node from 'heap', in O(1), maintaining the heap
|
|
|
|
|
* invariant. Returns the node removed.
|
|
|
|
|
*
|
|
|
|
|
* The caller must ensure that 'heap' contains at least one element. */
|
|
|
|
|
static inline struct heap_node *
|
|
|
|
|
heap_pop(struct heap *heap)
|
|
|
|
|
{
|
|
|
|
|
return heap->array[heap->n--];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Changes the priority of 'node' (which must be in 'heap') to 'priority'.
|
|
|
|
|
*
|
|
|
|
|
* After this call, heap_max() will no longer necessarily return the maximum
|
|
|
|
|
* value in the heap, and HEAP_FOR_EACH will no longer necessarily iterate in
|
|
|
|
|
* heap level order, until the next call to heap_rebuild(heap).
|
|
|
|
|
*
|
|
|
|
|
* This takes time O(1). */
|
|
|
|
|
static inline void
|
2013-10-16 03:32:31 +00:00
|
|
|
|
heap_raw_change(struct heap_node *node, uint64_t priority)
|
2012-01-24 15:07:41 -08:00
|
|
|
|
{
|
|
|
|
|
node->priority = priority;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif /* heap.h */
|