This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
yap-6.3/packages/udi/b+tree/b+tree.c
2015-10-13 08:17:51 +01:00

355 lines
6.9 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "b+tree_private.h"
btree_t BTreeNew (void)
{
btree_t t;
t = BTreeNewNode();
t->level = 0; /*leaf*/
return t;
}
void BTreeDestroy (btree_t t)
{
if (t)
BTreeDestroyNode (t);
}
static void BTreeDestroyNode (node_t n)
{
int i;
if (n->level == 0)
{
for (i = 0; i < n->count; i++)
;/* allow user free data*/
}
else
{
for (i = 0; i < n->count; i++)
BTreeDestroyNode (n->branch[i].child);
}
}
static node_t BTreeNewNode (void)
{
node_t n;
n = (node_t) malloc (SIZEOF_NODE);
assert(n);
BTreeNodeInit(n);
return n;
}
static void BTreeNodeInit (node_t n)
{
memset((void *) n,0, SIZEOF_NODE);
n->level = -1;
}
void *BTreeMin (node_t n, node_t *f, int *i)
{
if (n->level > 0)
return BTreeMin((node_t) n->branch[0].child, f, i);
else
{
if(f)
*f = n;
if(i)
*i = 0;
return n->branch[0].child;
}
}
void *BTreeMax (node_t n, node_t *f, int *i)
{
if (n->level > 0)
return BTreeMax((node_t) n->branch[n->count].child, f, i);
else
{
if(n->count > 0)
{
if(f)
*f = n;
if(i)
*i = n->count - 1;
return n->branch[n->count - 1].child;
}
}
if (f)
*f = NULL;
if (i)
*i = -1;
return NULL;
}
void * BTreeSearch (node_t n, double k, int s, node_t *f, int *i)
{
int j;
assert(s == EQ || s == GE || s == GT);
if (n->level > 0)
{
for (j = 0; j < n->count; j++)
if (n->branch[j].key >= k)
return BTreeSearch((node_t) n->branch[j].child,k,s,f,i);
return BTreeSearch((node_t) n->branch[j].child,k,s,f,i);
}
else
{
if (s == EQ || s == GE) /*== or >=*/
for (j = 0; j < n->count; j++)
if (n->branch[j].key == k)
{
if (f)
*f = n;
if (i)
*i = j;
return n->branch[j].child;
}
if (s == GE || s == GT) /* >= or > */
{
if (f)
*f = n;
for (j = 0; j < n->count; j++)
if (n->branch[j].key > k)
{
if (i)
*i = j;
return n->branch[j].child;
}
}
}
if (f)
*f = NULL;
if (i)
*i = -1;
return NULL;
}
void *BTreeSearchNext (double max, int s, node_t *n, int *i)
{
assert(n && i);
assert(s == LT || s == LE);
if (*i == (*n)->count - 1)
{
if (!(*n)->branch[MAXCARD - 1].child) /*terminou*/
return NULL;
*n = (node_t) (*n)->branch[MAXCARD - 1].child;
*i = 0;
}
else
(*i) ++;
if ((*n)->branch[*i].key > max ||
((*n)->branch[*i].key == max && s == LT))
return NULL;
return (*n)->branch[*i].child;
}
void BTreeInsert (btree_t *t, double k, void *ptr)
{
node_t new_root;
assert(t && *t);
if (BTreeInsertNode(*t,&k,&ptr))
/* deal with root split */
{
new_root = BTreeNewNode();
new_root->level = (*t)->level + 1;
new_root->count = 1;
new_root->branch[0].key = k;
new_root->branch[0].child = (void *) (*t);
new_root->branch[1].child = ptr;
*t = new_root;
}
}
static int BTreeInsertNode(node_t n, double *k, void **ptr)
/*ptr holds data and can return node_t*/
{
int i;
assert(n);
if (n->level > 0)
{
i = BTreePickBranch(n,*k);
if (!BTreeInsertNode((node_t) n->branch[i].child, k, ptr))
/*not split */
{
return FALSE;
}
else
/* node split */
{
return BTreeAddBranch(n, i, k, ptr); /*propagate split*/
}
}
else
{
return BTreeAddLeaf(n,k,ptr);
}
}
static int BTreeAddBranch(node_t n, int idx, double *k,
void **ptr)
{
int i,j;
double key[MAXCARD];
void *branch[MAXCARD+1];
int level;
node_t t;
if (n->count < MAXCARD - 1)
{
i = n->count;
if (i > 0)
for(; n->branch[i-1].key > *k ; i--)
{
n->branch[i].key = n->branch[i-1].key;
n->branch[i+1].child = n->branch[i].child;
}
n->branch[i].key = *k;
n->branch[i+1].child = *ptr;
n->branch[i].child = n->branch[idx].child;
n->count ++;
return FALSE;
}
else
{
for(i = n->count, j = MAXCARD;
n->branch[i - 1].key > *k;
i--, j--)
{
key[j - 1] = n->branch[i - 1].key;
branch[j] = n->branch[i].child;
}
key[j - 1] = *k;
branch[j - 1] = n->branch[idx].child;
branch[j] = *ptr;
j--;
for(; i > 0;i--,j--)
{
key[j-1] = n->branch[i-1].key;
branch[j-1] = n->branch[i-1].child;
}
level = n->level;
BTreeNodeInit(n);
n->level = level;
t = BTreeNewNode();
t->level = level;
for (i = 0; i < MAXCARD / 2; i ++)
{
n->branch[i].key = key[i];
n->branch[i].child = branch[i];
n->count ++;
}
n->branch[i].child = branch[i];
*k = key[i];
*ptr = t;
for (j = 0,i++; i < MAXCARD; j ++, i ++)
{
t->branch[j].key = key[i];
t->branch[j].child = branch[i];
t->count ++;
}
t->branch[j].child = branch[i];
return TRUE;
}
}
static int BTreePickBranch(node_t n, double k)
{
int i;
for (i = 0; i < n->count; i++)
if (n->branch[i].key > k)
return i;
return i;
}
static int BTreeAddLeaf(node_t n, double *k, void **ptr)
{
int i,j;
node_t t;
double key[MAXCARD];
void *branch[MAXCARD];
assert(n);
if (n->count < MAXCARD - 1) /*split not necessary*/
{
i = n->count;
if (i > 0)
for (; n->branch[i - 1].key > *k; i--)
{
n->branch[i].key = n->branch[i-1].key;
n->branch[i].child = n->branch[i-1].child;
}
n->branch[i].key = *k;
n->branch[i].child = *ptr;
n->count ++;
return FALSE;
}
else /*needs to split*/
{
for(i = n->count - 1, j = MAXCARD - 1;
n->branch[i].key > *k;
i--, j--)
{
key[j] = n->branch[i].key;
branch[j] = n->branch[i].child;
}
key[j] = *k;
branch[j] = *ptr;
j--;
for(; i >= 0;i--,j--)
{
key[j] = n->branch[i].key;
branch[j] = n->branch[i].child;
}
n->count = 0;
t = BTreeNewNode();
t->level = n->level;
for (i = 0; i <= MAXCARD / 2; i ++)
{
n->branch[i].key = key[i];
n->branch[i].child = branch[i];
n->count ++;
}
*k = key[i-1];
*ptr = t;
for (j = 0; i < MAXCARD; j ++, i ++)
{
t->branch[j].key = key[i];
t->branch[j].child = branch[i];
t->count ++;
}
/*linked list*/
t->branch[MAXCARD -1].child = n->branch[MAXCARD - 1].child;
n->branch[MAXCARD -1].child = t;
return TRUE;
}
}