Part II • Managing Data in C
Listing 10.6. continued
#include <stdlib.h> |
// For standard functions |
#include <stdio.h> |
// Make includes first part of file |
#include <string.h> |
// For string functions |
#include <process.h> |
// For exit(), etc. |
#include <malloc.h> |
// For malloc(), calloc(), realloc(), free() |
#include <search.h> |
// For qsort() |
#include <time.h> |
// To initialize the random-number functions |
/* B-tree search and add, find, and delete
*Adapted from
*ALGORITHMS+DATA STRUCTURES=PROGRAMS by N. Wirth
* |
Implemented |
for BDS |
C by H. Katayose (JUG-CP/M No.179) |
* |
Implemented |
for ANSI |
C by P. Hipson (CUG) |
*/ |
|
|
|
/* PAGE_SIZE is |
better at 8 (less memory fragmentation) */ |
#define PAGE_SIZE |
2 |
#define HALF_PAGE_SIZE |
(PAGE_SIZE / 2) |
#define PAGE |
|
struct _page |
#define ITEM |
|
struct _item |
#define ROOT |
0 |
|
#define RIGHT |
1 |
|
#define LEFT |
2 |
|
#define TRUE |
(1) |
|
#define FALSE |
(0) |
|
/* Storage allocation structures used by malloc() */
struct _header |
|
{ |
|
struct _header |
*_ptr; |
unsigned |
_size; |
}; |
|
Part II • Managing Data in C
Listing 10.6. continued
int |
nKeyValue; |
int |
h; |
int |
nLevelCount = 0; |
char |
chOperation; |
char |
szCommand[132]; |
PAGE |
*q; |
PAGE |
*root; |
ITEM |
u; |
printf(“\n\nBTREE: Demo program for B-trees\n” “\n”
“Command are:\n”
“A # - Adds key # (integer 0 - 32767).\n”
“D # - Deletes key # (integer 0 - 32767).\n”
“S # - Searches for key # (integer 0 - 32767).\n”
“R # - Adds # random keys (integer 0 - 2000).\n”
“H - Prints a help screen.\n”
“T - Prints the current B-tree structure.\n”
“X - Exits, after a confirming prompt.\n\n”);
root = NULL;
while (TRUE)
{
printf(“\n\nCommand ?”);
gets(szCommand);
sscanf(szCommand, “%c %d”, &chOperation, &nKeyValue);
switch(chOperation)
{
case ‘h’: case ‘H’:
PrintHelp();
break;
Part II • Managing Data in C
Listing 10.6. continued
printf(“SEARCH KEY %d NOT FOUND searching %d \ levels\n”,
nKeyValue,
nLevelCount);
}
break;
case ‘a’: case ‘A’:
printf(“ADD KEY %d\n”, nKeyValue);
if (SearchAndAdd(nKeyValue, root, &u))
{
q = root; NewItem(&root); root->nItemCount = 1; root->LeftReference = q;
CopyItem(&root->Item[0], &u);
}
TreePrint(root, 0, ROOT, 0);
break;
case ‘t’: case ‘T’:
printf(“PRINT TREE\n”);
TreePrint(root, 0, ROOT, 0);
break;
case ‘d’: case ‘D’:
printf(“DELETE KEY %d\n”, nKeyValue);
Part II • Managing Data in C
Listing 10.6. continued
PAGE *a,
ITEM *v)
{
int i;
ITEM u;
//printf(“Search()...\n”);
if (a == NULL)
{
return(FALSE);
}
for (i = 0; i < a->nItemCount && nKeyValue > a->Item[i].nKeyValue; i++)
{
;
}
if (nKeyValue == a->Item[i].nKeyValue && i < a->nItemCount)
{
return(TRUE);
}
else
{
++(*nLevelCount);
return(Search(nKeyValue, nLevelCount,
i ? a->Item[i - 1].RightReference : a->LeftReference, &u));
}
}
int SearchAndAdd( int nKeyValue, PAGE *a, ITEM *v)
Data Management: Sorts, Lists, and Indexes |
C C C |
|
10C |
|
C C C |
|
C C |
{
int i;
ITEM u;
//printf(“SearchAndAdd()...\n”);
if (a == NULL)
{
v->nKeyValue = nKeyValue; v->nCount = 1; v->RightReference = NULL; return TRUE;
}
for (i = 0; i < a->nItemCount && nKeyValue > a->Item[i].nKeyValue; i++)
{
;
}
if (nKeyValue == a->Item[i].nKeyValue && i < a->nItemCount)
{
a->Item[i].nCount++;
}
else
{
if (SearchAndAdd(nKeyValue,
i ? a->Item[i - 1].RightReference : a->LeftReference, &u))
{
return (Insert(a, i, &u, v));
}
}
return FALSE;
}
int Insert( PAGE *a,
continues
Part II • Managing Data in C
Listing 10.6. continued
int i, ITEM *u, ITEM *v)
//printf(“Insert()...\n”);
if (a->nItemCount < PAGE_SIZE)
{
for (j = a->nItemCount; j >= i + 1; j—)
{
CopyItem(&a->Item[j], &a->Item[j - 1]);
}
++a->nItemCount;
CopyItem(&a->Item[i], u);
return(FALSE);
}
else
{/* Page a is full. Split it and assign the emerging item to v. */
NewItem(&b);
if (i <= HALF_PAGE_SIZE)
{
if (i == HALF_PAGE_SIZE)
{
CopyItem(v, u);
}
else
{
CopyItem(v, &a->Item[HALF_PAGE_SIZE - 1]);
Data Management: Sorts, Lists, and Indexes
for (j = HALF_PAGE_SIZE - 1; j >= i + 1; j--)
{
CopyItem(&a->Item[j], &a->Item[j - 1]);
}
CopyItem(&a->Item[i], u);
}
for (j = 0; j <= HALF_PAGE_SIZE - 1; j++)
{
CopyItem(&b->Item[j], &a->Item[j + HALF_PAGE_SIZE]);
}
}
else
{
i -= HALF_PAGE_SIZE;
CopyItem(v, &a->Item[HALF_PAGE_SIZE]);
for (j = 0; j <= i - 2; j++)
{
CopyItem(&b->Item[j], &a->Item[j + HALF_PAGE_SIZE + 1]);
}
CopyItem(&b->Item[i - 1], u);
for (j = i; j <= HALF_PAGE_SIZE - 1; j++)
{
CopyItem(&b->Item[j], &a->Item[j + HALF_PAGE_SIZE]);
}
}
if (HALF_PAGE_SIZE == 0)
{
a->nItemCount = 1; b->nItemCount = 1;
}
else
{
a->nItemCount = HALF_PAGE_SIZE; b->nItemCount = HALF_PAGE_SIZE;
}
continues