3 changed files with 1559 additions and 2 deletions
-
4Makefile.am
-
304include/ut0rbt.h
-
1253ut/ut0rbt.c
@ -0,0 +1,304 @@ |
|||
/****************************************************** |
|||
Red-Black tree implementation. |
|||
(c) 2007 Oracle/Innobase Oy |
|||
|
|||
Created 2007-03-20 Sunny Bains |
|||
*******************************************************/ |
|||
|
|||
#ifndef INNOBASE_UT0RBT_H |
|||
#define INNOBASE_UT0RBT_H |
|||
|
|||
#if !defined(IB_RBT_TESTING) |
|||
#include "univ.i" |
|||
#include "ut0mem.h" |
|||
#else |
|||
#include <stdio.h> |
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
#include <assert.h> |
|||
|
|||
#define ut_malloc malloc |
|||
#define ut_free free |
|||
#define ulint unsigned long |
|||
#define ut_a(c) assert(c) |
|||
#define ut_error assert(0) |
|||
#define ibool unsigned int |
|||
#define TRUE 1 |
|||
#define FALSE 0 |
|||
#endif |
|||
|
|||
/* Red black tree typedefs */ |
|||
typedef struct ib_rbt_struct ib_rbt_t; |
|||
typedef struct ib_rbt_node_struct ib_rbt_node_t; |
|||
// FIXME: Iterator is a better name than _bound_ |
|||
typedef struct ib_rbt_bound_struct ib_rbt_bound_t; |
|||
typedef void (*ib_rbt_print_node)(const ib_rbt_node_t* node); |
|||
typedef int (*ib_rbt_compare)(const void* p1, const void* p2); |
|||
|
|||
/* Red black tree color types */ |
|||
enum ib_rbt_color_enum { |
|||
IB_RBT_RED, |
|||
IB_RBT_BLACK |
|||
}; |
|||
|
|||
typedef enum ib_rbt_color_enum ib_rbt_color_t; |
|||
|
|||
/* Red black tree node */ |
|||
struct ib_rbt_node_struct { |
|||
ib_rbt_color_t color; /* color of this node */ |
|||
|
|||
ib_rbt_node_t* left; /* points left child */ |
|||
ib_rbt_node_t* right; /* points right child */ |
|||
ib_rbt_node_t* parent; /* points parent node */ |
|||
|
|||
char value[1]; /* Data value */ |
|||
}; |
|||
|
|||
/* Red black tree instance.*/ |
|||
struct ib_rbt_struct { |
|||
ib_rbt_node_t* nil; /* Black colored node that is |
|||
used as a sentinel. This is |
|||
pre-allocated too.*/ |
|||
|
|||
ib_rbt_node_t* root; /* Root of the tree, this is |
|||
pre-allocated and the first |
|||
data node is the left child.*/ |
|||
|
|||
ulint n_nodes; /* Total number of data nodes */ |
|||
|
|||
ib_rbt_compare compare; /* Fn. to use for comparison */ |
|||
ulint sizeof_value; /* Sizeof the item in bytes */ |
|||
}; |
|||
|
|||
/* The result of searching for a key in the tree, this is useful for |
|||
a speedy lookup and insert if key doesn't exist.*/ |
|||
struct ib_rbt_bound_struct { |
|||
const ib_rbt_node_t* |
|||
last; /* Last node visited */ |
|||
|
|||
int result; /* Result of comparing with |
|||
the last non-nil node that |
|||
was visited */ |
|||
}; |
|||
|
|||
/* Size in elements (t is an rb tree instance) */ |
|||
#define rbt_size(t) (t->n_nodes) |
|||
|
|||
/* Check whether the rb tree is empty (t is an rb tree instance) */ |
|||
#define rbt_empty(t) (rbt_size(t) == 0) |
|||
|
|||
/* Get data value (t is the data type, n is an rb tree node instance) */ |
|||
#define rbt_value(t, n) ((t*) &n->value[0]) |
|||
|
|||
/* Compare a key with the node value (t is tree, k is key, n is node)*/ |
|||
#define rbt_compare(t, k, n) (t->compare(k, n->value)) |
|||
|
|||
/************************************************************************ |
|||
Free an instance of a red black tree */ |
|||
extern |
|||
void |
|||
rbt_free( |
|||
/*=====*/ |
|||
ib_rbt_t* tree); /* in: rb tree to free */ |
|||
/************************************************************************ |
|||
Create an instance of a red black tree */ |
|||
extern |
|||
ib_rbt_t* |
|||
rbt_create( |
|||
/*=======*/ |
|||
/* out: rb tree instance */ |
|||
size_t sizeof_value, /* in: size in bytes */ |
|||
ib_rbt_compare compare); /* in: comparator */ |
|||
/************************************************************************ |
|||
Delete a node from the red black tree, identified by key */ |
|||
extern |
|||
ibool |
|||
rbt_delete( |
|||
/*=======*/ |
|||
/* in: TRUE on success */ |
|||
ib_rbt_t* tree, /* in: rb tree */ |
|||
const void* key); /* in: key to delete */ |
|||
/************************************************************************ |
|||
Remove a node from the red black tree, NOTE: This function will not delete |
|||
the node instance, THAT IS THE CALLERS RESPONSIBILITY.*/ |
|||
extern |
|||
ib_rbt_node_t* |
|||
rbt_remove_node( |
|||
/*============*/ |
|||
/* out: the deleted node |
|||
with the const.*/ |
|||
ib_rbt_t* tree, /* in: rb tree */ |
|||
const ib_rbt_node_t* |
|||
node); /* in: node to delete, this |
|||
is a fudge and declared const |
|||
because the caller has access |
|||
only to const nodes.*/ |
|||
/************************************************************************ |
|||
Return a node from the red black tree, identified by |
|||
key, NULL if not found */ |
|||
extern |
|||
const ib_rbt_node_t* |
|||
rbt_lookup( |
|||
/*=======*/ |
|||
/* out: node if found else |
|||
return NULL*/ |
|||
const ib_rbt_t* tree, /* in: rb tree to search */ |
|||
const void* key); /* in: key to lookup */ |
|||
/************************************************************************ |
|||
Add data to the red black tree, identified by key (no dups yet!)*/ |
|||
extern |
|||
const ib_rbt_node_t* |
|||
rbt_insert( |
|||
/*=======*/ |
|||
/* out: inserted node */ |
|||
ib_rbt_t* tree, /* in: rb tree */ |
|||
const void* key, /* in: key for ordering */ |
|||
const void* value); /* in: data that will be |
|||
copied to the node.*/ |
|||
/************************************************************************ |
|||
Add a new node to the tree, useful for data that is pre-sorted.*/ |
|||
extern |
|||
const ib_rbt_node_t* |
|||
rbt_add_node( |
|||
/*=========*/ |
|||
/* out: appended node */ |
|||
ib_rbt_t* tree, /* in: rb tree */ |
|||
ib_rbt_bound_t* parent, /* in: parent */ |
|||
const void* value); /* in: this value is copied |
|||
to the node */ |
|||
/************************************************************************ |
|||
Return the left most data node in the tree*/ |
|||
extern |
|||
const ib_rbt_node_t* |
|||
rbt_first( |
|||
/*======*/ |
|||
/* out: left most node */ |
|||
const ib_rbt_t* tree); /* in: rb tree */ |
|||
/************************************************************************ |
|||
Return the right most data node in the tree*/ |
|||
extern |
|||
const ib_rbt_node_t* |
|||
rbt_last( |
|||
/*=====*/ |
|||
/* out: right most node */ |
|||
const ib_rbt_t* tree); /* in: rb tree */ |
|||
/************************************************************************ |
|||
Return the next node from current.*/ |
|||
extern |
|||
const ib_rbt_node_t* |
|||
rbt_next( |
|||
/*=====*/ |
|||
/* out: successor node to |
|||
current that is passed in.*/ |
|||
const ib_rbt_t* tree, /* in: rb tree */ |
|||
const ib_rbt_node_t* /* in: current node */ |
|||
current); |
|||
/************************************************************************ |
|||
Return the prev node from current.*/ |
|||
extern |
|||
const ib_rbt_node_t* |
|||
rbt_prev( |
|||
/*=====*/ |
|||
/* out: precedessor node to |
|||
current that is passed in */ |
|||
const ib_rbt_t* tree, /* in: rb tree */ |
|||
const ib_rbt_node_t* /* in: current node */ |
|||
current); |
|||
/************************************************************************ |
|||
Find the node that has the lowest key that is >= key.*/ |
|||
extern |
|||
const ib_rbt_node_t* |
|||
rbt_lower_bound( |
|||
/*============*/ |
|||
/* out: node that satisfies |
|||
the lower bound constraint or |
|||
NULL */ |
|||
const ib_rbt_t* tree, /* in: rb tree */ |
|||
const void* key); /* in: key to search */ |
|||
/************************************************************************ |
|||
Find the node that has the greatest key that is <= key.*/ |
|||
extern |
|||
const ib_rbt_node_t* |
|||
rbt_upper_bound( |
|||
/*============*/ |
|||
/* out: node that satisifies |
|||
the upper bound constraint or |
|||
NULL */ |
|||
const ib_rbt_t* tree, /* in: rb tree */ |
|||
const void* key); /* in: key to search */ |
|||
/************************************************************************ |
|||
Search for the key, a node will be retuned in parent.last, whether it |
|||
was found or not. If not found then parent.last will contain the |
|||
parent node for the possibly new key otherwise the matching node.*/ |
|||
extern |
|||
int |
|||
rbt_search( |
|||
/*=======*/ |
|||
/* out: result of last |
|||
comparison */ |
|||
const ib_rbt_t* tree, /* in: rb tree */ |
|||
ib_rbt_bound_t* parent, /* in: search bounds */ |
|||
const void* key); /* in: key to search */ |
|||
/************************************************************************ |
|||
Search for the key, a node will be retuned in parent.last, whether it |
|||
was found or not. If not found then parent.last will contain the |
|||
parent node for the possibly new key otherwise the matching node.*/ |
|||
extern |
|||
int |
|||
rbt_search_cmp( |
|||
/*===========*/ |
|||
/* out: result of last |
|||
comparison */ |
|||
const ib_rbt_t* tree, /* in: rb tree */ |
|||
ib_rbt_bound_t* parent, /* in: search bounds */ |
|||
const void* key, /* in: key to search */ |
|||
ib_rbt_compare compare); /* in: comparator */ |
|||
/************************************************************************ |
|||
Clear the tree, deletes (and free's) all the nodes.*/ |
|||
extern |
|||
void |
|||
rbt_clear( |
|||
/*======*/ |
|||
ib_rbt_t* tree); /* in: rb tree */ |
|||
/************************************************************************ |
|||
Merge the node from dst into src. Return the number of nodes merged.*/ |
|||
extern |
|||
ulint |
|||
rbt_merge_uniq( |
|||
/*===========*/ |
|||
/* out: no. of recs merged */ |
|||
ib_rbt_t* dst, /* in: dst rb tree */ |
|||
const ib_rbt_t* src); /* in: src rb tree */ |
|||
/************************************************************************ |
|||
Merge the node from dst into src. Return the number of nodes merged. |
|||
Delete the nodes from src after copying node to dst. As a side effect |
|||
the duplicates will be left untouched in the src, since we don't support |
|||
duplicates (yet). NOTE: src and dst must be similar, the function doesn't |
|||
check for this condition (yet).*/ |
|||
extern |
|||
ulint |
|||
rbt_merge_uniq_destructive( |
|||
/*=======================*/ |
|||
/* out: no. of recs merged */ |
|||
ib_rbt_t* dst, /* in: dst rb tree */ |
|||
ib_rbt_t* src); /* in: src rb tree */ |
|||
/************************************************************************ |
|||
Verify the integrity of the RB tree. For debugging. 0 failure else height |
|||
of tree (in count of black nodes).*/ |
|||
extern |
|||
ibool |
|||
rbt_validate( |
|||
/*=========*/ |
|||
/* out: TRUE if OK |
|||
FALSE if tree invalid.*/ |
|||
const ib_rbt_t* tree); /* in: tree to validate */ |
|||
/************************************************************************ |
|||
Iterate over the tree in depth first order.*/ |
|||
extern |
|||
void |
|||
rbt_print( |
|||
/*======*/ |
|||
const ib_rbt_t* tree, /* in: tree to traverse */ |
|||
ib_rbt_print_node print); /* in: print function */ |
|||
|
|||
#endif /* INNOBASE_UT0RBT_H */ |
|||
1253
ut/ut0rbt.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
Write
Preview
Loading…
Cancel
Save
Reference in new issue