diff options
author | Masahiko Sawada <msawada@postgresql.org> | 2024-04-03 10:44:21 +0900 |
---|---|---|
committer | Masahiko Sawada <msawada@postgresql.org> | 2024-04-03 10:44:21 +0900 |
commit | b840508644151232b6ca1287dde617ed00ba2bdf (patch) | |
tree | 586848cf7a5b1657185ae5f9fe10ae4dc8505bb9 /src/include/lib/binaryheap.h | |
parent | bcb14f4abca0c309f908b3f0cd64378785c99795 (diff) | |
download | postgresql-b840508644151232b6ca1287dde617ed00ba2bdf.tar.gz postgresql-b840508644151232b6ca1287dde617ed00ba2bdf.zip |
Add functions to binaryheap for efficient key removal and update.
Previously, binaryheap didn't support updating a key and removing a
node in an efficient way. For example, in order to remove a node from
the binaryheap, the caller had to pass the node's position within the
array that the binaryheap internally has. Removing a node from the
binaryheap is done in O(log n) but searching for the key's position is
done in O(n).
This commit adds a hash table to binaryheap in order to track the
position of each nodes in the binaryheap. That way, by using newly
added functions such as binaryheap_update_up() etc., both updating a
key and removing a node can be done in O(1) on an average and O(log n)
in worst case. This is known as the indexed binary heap. The caller
can specify to use the indexed binaryheap by passing indexed = true.
The current code does not use the new indexing logic, but it will be
used by an upcoming patch.
Reviewed-by: Vignesh C, Peter Smith, Hayato Kuroda, Ajin Cherian,
Tomas Vondra, Shubham Khanna
Discussion: https://postgr.es/m/CAD21AoDffo37RC-eUuyHJKVEr017V2YYDLyn1xF_00ofptWbkg%40mail.gmail.com
Diffstat (limited to 'src/include/lib/binaryheap.h')
-rw-r--r-- | src/include/lib/binaryheap.h | 36 |
1 files changed, 35 insertions, 1 deletions
diff --git a/src/include/lib/binaryheap.h b/src/include/lib/binaryheap.h index 9f6efb06e3a..4c1a1bb274b 100644 --- a/src/include/lib/binaryheap.h +++ b/src/include/lib/binaryheap.h @@ -30,6 +30,29 @@ typedef Datum bh_node_type; typedef int (*binaryheap_comparator) (bh_node_type a, bh_node_type b, void *arg); /* + * Struct for a hash table element to store the node's index in the bh_nodes + * array. + */ +typedef struct bh_nodeidx_entry +{ + bh_node_type key; + int index; /* entry's index within the node array */ + char status; /* hash status */ + uint32 hash; /* hash values (cached) */ +} bh_nodeidx_entry; + +/* Define parameters necessary to generate the hash table interface. */ +#define SH_PREFIX bh_nodeidx +#define SH_ELEMENT_TYPE bh_nodeidx_entry +#define SH_KEY_TYPE bh_node_type +#define SH_SCOPE extern +#ifdef FRONTEND +#define SH_RAW_ALLOCATOR pg_malloc0 +#endif +#define SH_DECLARE +#include "lib/simplehash.h" + +/* * binaryheap * * bh_size how many nodes are currently in "nodes" @@ -47,11 +70,18 @@ typedef struct binaryheap binaryheap_comparator bh_compare; void *bh_arg; bh_node_type *bh_nodes; + + /* + * If bh_nodeidx is not NULL, the bh_nodeidx is used to track of each + * node's index in bh_nodes. This enables the caller to perform + * binaryheap_remove_node_ptr(), binaryheap_update_up/down in O(log n). + */ + bh_nodeidx_hash *bh_nodeidx; } binaryheap; extern binaryheap *binaryheap_allocate(int num_nodes, binaryheap_comparator compare, - void *arg); + bool indexed, void *arg); extern void binaryheap_reset(binaryheap *heap); extern void binaryheap_free(binaryheap *heap); extern void binaryheap_add_unordered(binaryheap *heap, bh_node_type d); @@ -60,10 +90,14 @@ extern void binaryheap_add(binaryheap *heap, bh_node_type d); extern bh_node_type binaryheap_first(binaryheap *heap); extern bh_node_type binaryheap_remove_first(binaryheap *heap); extern void binaryheap_remove_node(binaryheap *heap, int n); +extern void binaryheap_remove_node_ptr(binaryheap *heap, bh_node_type d); extern void binaryheap_replace_first(binaryheap *heap, bh_node_type d); +extern void binaryheap_update_up(binaryheap *heap, bh_node_type d); +extern void binaryheap_update_down(binaryheap *heap, bh_node_type d); #define binaryheap_empty(h) ((h)->bh_size == 0) #define binaryheap_size(h) ((h)->bh_size) #define binaryheap_get_node(h, n) ((h)->bh_nodes[n]) +#define binaryheap_indexed(h) ((h)->bh_nodeidx != NULL) #endif /* BINARYHEAP_H */ |