355 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			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;
 | 
						|
    }
 | 
						|
}
 |