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;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 |