mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-26 18:04:07 +00:00
Upload
Digital Research
This commit is contained in:
19
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/avl-subs/Makefile
Normal file
19
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/avl-subs/Makefile
Normal file
@@ -0,0 +1,19 @@
|
||||
# makefile for tree stuff
|
||||
# vix 24jul87 [stripped down from as makefile]
|
||||
|
||||
CFLAGS = -O
|
||||
|
||||
TRTEST_OBJ = t_trtest.o tree.o
|
||||
|
||||
all : t_trtest
|
||||
|
||||
t_trtest : $(TRTEST_OBJ)
|
||||
cc -o t_trtest $(TRTEST_OBJ)
|
||||
|
||||
clean : FRC
|
||||
rm -f core a.out t_trtest $(TRTEST_OBJ)
|
||||
|
||||
FRC :
|
||||
|
||||
tree.o : tree.c tree.h vixie.h
|
||||
t_trtest.o : t_trtest.c tree.h vixie.h
|
||||
23
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/avl-subs/README
Normal file
23
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/avl-subs/README
Normal file
@@ -0,0 +1,23 @@
|
||||
AVL Trees V1.0
|
||||
24-July-1987
|
||||
Paul Vixie
|
||||
|
||||
This library and test program are useful for creating and using balanced
|
||||
binary trees (AVL trees). The tree is held in memory, using malloc(3) to
|
||||
allocate storage. A better version would allow file-based trees in
|
||||
addition; once memory mapped files hit the UNIX(tm) community, this will
|
||||
be much easier to do. In the meanwhile, these routines have been very
|
||||
useful to be for symbol tables and the like. (Yes, I'm sure hashing is
|
||||
better in some way, but I've used this for symbol tables, just the same.)
|
||||
|
||||
I cannot take credit for the algorithms. See "Algorithms & Data Structures,"
|
||||
Niklaus Wirth, Prentice-Hall 1986, ISBN 0-13-022005-1. This is an update of
|
||||
Wirth's previous book, titled "Algorythms + Data Structures = Programs,"
|
||||
which used Pascal as the language for examples. This later book uses the
|
||||
newer Modula-2 for it's examples; this tree code was created using the
|
||||
Modula-2 examples as guidelines. At the time I typed this stuff in (about
|
||||
a year ago, in July 1987), I understood how it all worked. Today, well...
|
||||
|
||||
This code is hereby placed in the public domain, unless restrictions apply
|
||||
from Prentice-Hall on the algorithms themselves. If you use or redistribute
|
||||
this code, please leave my name (and Wirth's) in the comments.
|
||||
126
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/avl-subs/t_trtest.c
Normal file
126
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/avl-subs/t_trtest.c
Normal file
@@ -0,0 +1,126 @@
|
||||
/* t_trtest - test the tree functions
|
||||
* vix 24jul87 [documented, added savestr for net distribution]
|
||||
*/
|
||||
|
||||
#define MAIN
|
||||
|
||||
#include <stdio.h>
|
||||
#include "vixie.h"
|
||||
#include "tree.h"
|
||||
|
||||
main()
|
||||
{
|
||||
tree *t;
|
||||
char line[100];
|
||||
|
||||
tree_init(&t);
|
||||
while (printf("line (or .): "), gets(line), line[0] != '.')
|
||||
{
|
||||
if (strncmp(line, "~r ", 3)) {
|
||||
trtest(&t, line, 1);
|
||||
}
|
||||
else {
|
||||
FILE *f;
|
||||
|
||||
if (!(f = fopen(&line[3], "r")))
|
||||
perror(&line[3]);
|
||||
else {
|
||||
while (fgets(line, 100, f)) {
|
||||
line[strlen(line)-1] = '\0';
|
||||
printf("(%s)\n", line);
|
||||
trtest(&t, line, 0);
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trtest(tt, line, inter)
|
||||
tree **tt;
|
||||
char *line;
|
||||
{
|
||||
char opts[100], *tree_srch(), *pc, *n;
|
||||
int uar_print(), duar(), compar(), opt, status;
|
||||
|
||||
pc = tree_srch(tt, compar, line);
|
||||
printf("tree_srch=%08lx\n", pc);
|
||||
if (pc)
|
||||
{
|
||||
printf(" <%s>\n", pc);
|
||||
|
||||
if (inter) {
|
||||
printf("delete? "); gets(opts); opt = (opts[0]=='y');
|
||||
}
|
||||
else
|
||||
opt = 1;
|
||||
|
||||
if (opt) {
|
||||
status = tree_delete(tt, compar, line, duar);
|
||||
printf("delete=%d\n", status);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (inter) {
|
||||
printf("add? "); gets(opts); opt = (opts[0]=='y');
|
||||
}
|
||||
else
|
||||
opt = 1;
|
||||
|
||||
if (opt) {
|
||||
char *savestr();
|
||||
|
||||
n = savestr(line);
|
||||
tree_add(tt, compar, n, duar);
|
||||
}
|
||||
}
|
||||
tree_trav1(*tt, 0);
|
||||
}
|
||||
|
||||
duar(pc)
|
||||
char *pc;
|
||||
{
|
||||
printf("duar called, pc=%08X: <%s>\n", pc, pc?pc:"");
|
||||
free(pc);
|
||||
}
|
||||
|
||||
tree_trav1(t, l)
|
||||
tree *t;
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!t) return;
|
||||
tree_trav1(t->tree_l, l+1);
|
||||
for (i=0; i<l; i++) printf(" ");
|
||||
printf("%08lx (%s)\n", t->tree_p, t->tree_p);
|
||||
tree_trav1(t->tree_r, l+1);
|
||||
}
|
||||
|
||||
uar_print(pc)
|
||||
char *pc;
|
||||
{
|
||||
printf("uar_print(%08lx)", pc);
|
||||
if (pc)
|
||||
printf(" '%s'", pc);
|
||||
putchar('\n');
|
||||
return 1;
|
||||
}
|
||||
|
||||
compar(l, r)
|
||||
char *l, *r;
|
||||
{
|
||||
printf("compar(%s,%s)=%d\n", l, r, strcmp(l, r));
|
||||
return strcmp(l, r);
|
||||
}
|
||||
|
||||
char *
|
||||
savestr(str)
|
||||
char *str;
|
||||
{
|
||||
char *save;
|
||||
|
||||
save = malloc(strlen(str) + 1);
|
||||
strcpy(save, str);
|
||||
return save;
|
||||
}
|
||||
511
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/avl-subs/tree.c
Normal file
511
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/avl-subs/tree.c
Normal file
@@ -0,0 +1,511 @@
|
||||
/* as_tree - tree library for as
|
||||
* vix 14dec85 [written]
|
||||
* vix 02feb86 [added tree balancing from wirth "a+ds=p" p. 220-221]
|
||||
* vix 06feb86 [added tree_mung()]
|
||||
* vix 20jun86 [added tree_delete per wirth a+ds (mod2 v.) p. 224]
|
||||
* vix 23jun86 [added delete uar to add for replaced nodes]
|
||||
*/
|
||||
|
||||
|
||||
/* This program text was created by Paul Vixie using examples from the book:
|
||||
* "Algorithms & Data Structures," Niklaus Wirth, Prentice-Hall, 1986, ISBN
|
||||
* 0-13-022005-1. This code and associated documentation is hereby placed
|
||||
* in the public domain.
|
||||
*/
|
||||
|
||||
|
||||
/*#define DEBUG "tree"*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "vixie.h"
|
||||
#include "tree.h"
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
#define MSG(msg) printf("DEBUG: '%s'\n", msg);
|
||||
#else
|
||||
#define MSG(msg)
|
||||
#endif
|
||||
|
||||
|
||||
void tree_init(ppr_tree)
|
||||
tree **ppr_tree;
|
||||
{
|
||||
ENTER("tree_init")
|
||||
*ppr_tree = NULL;
|
||||
EXITV
|
||||
}
|
||||
|
||||
|
||||
char *tree_srch(ppr_tree, pfi_compare, pc_user)
|
||||
tree **ppr_tree;
|
||||
int (*pfi_compare)();
|
||||
char *pc_user;
|
||||
{
|
||||
register int i_comp;
|
||||
register tree *pr_new;
|
||||
|
||||
ENTER("tree_srch")
|
||||
|
||||
if (*ppr_tree)
|
||||
{
|
||||
i_comp = (*pfi_compare)(pc_user, (**ppr_tree).tree_p);
|
||||
if (i_comp > 0)
|
||||
EXIT(tree_srch(
|
||||
&(**ppr_tree).tree_r,
|
||||
pfi_compare,
|
||||
pc_user
|
||||
))
|
||||
if (i_comp < 0)
|
||||
EXIT(tree_srch(
|
||||
&(**ppr_tree).tree_l,
|
||||
pfi_compare,
|
||||
pc_user
|
||||
))
|
||||
|
||||
/* not higher, not lower... this must be the one.
|
||||
*/
|
||||
EXIT((**ppr_tree).tree_p)
|
||||
}
|
||||
|
||||
/* grounded. NOT found.
|
||||
*/
|
||||
EXIT(NULL)
|
||||
}
|
||||
|
||||
|
||||
void tree_add(ppr_tree, pfi_compare, pc_user, pfi_delete)
|
||||
tree **ppr_tree;
|
||||
int (*pfi_compare)();
|
||||
char *pc_user;
|
||||
int (*pfi_delete)();
|
||||
{
|
||||
void sprout();
|
||||
int i_balance = FALSE;
|
||||
|
||||
ENTER("tree_add")
|
||||
sprout(ppr_tree, pc_user, &i_balance, pfi_compare, pfi_delete);
|
||||
EXITV
|
||||
}
|
||||
|
||||
|
||||
static void sprout(ppr, pc_data, pi_balance, pfi_compare, pfi_delete)
|
||||
tree **ppr;
|
||||
char *pc_data;
|
||||
int *pi_balance;
|
||||
int (*pfi_compare)();
|
||||
int (*pfi_delete)();
|
||||
{
|
||||
tree *p1, *p2;
|
||||
int cmp;
|
||||
|
||||
ENTER("sprout")
|
||||
|
||||
/* are we grounded? if so, add the node "here" and set the rebalance
|
||||
* flag, then exit.
|
||||
*/
|
||||
if (!*ppr) {
|
||||
MSG("grounded. adding new node, setting h=true")
|
||||
*ppr = (tree *) malloc(sizeof(tree));
|
||||
(*ppr)->tree_l = NULL;
|
||||
(*ppr)->tree_r = NULL;
|
||||
(*ppr)->tree_b = 0;
|
||||
(*ppr)->tree_p = pc_data;
|
||||
*pi_balance = TRUE;
|
||||
EXITV
|
||||
}
|
||||
|
||||
/* compare the data using routine passed by caller.
|
||||
*/
|
||||
cmp = (*pfi_compare)(pc_data, (*ppr)->tree_p);
|
||||
|
||||
/* if LESS, prepare to move to the left.
|
||||
*/
|
||||
if (cmp < 0) {
|
||||
MSG("LESS. sprouting left.")
|
||||
sprout(&(*ppr)->tree_l, pc_data, pi_balance,
|
||||
pfi_compare, pfi_delete);
|
||||
if (*pi_balance) { /* left branch has grown longer */
|
||||
MSG("LESS: left branch has grown")
|
||||
switch ((*ppr)->tree_b)
|
||||
{
|
||||
case 1: /* right branch WAS longer; balance is ok now */
|
||||
MSG("LESS: case 1.. balnce restored implicitly")
|
||||
(*ppr)->tree_b = 0;
|
||||
*pi_balance = FALSE;
|
||||
break;
|
||||
case 0: /* balance WAS okay; now left branch longer */
|
||||
MSG("LESS: case 0.. balnce bad but still ok")
|
||||
(*ppr)->tree_b = -1;
|
||||
break;
|
||||
case -1:
|
||||
/* left branch was already too long. rebalnce */
|
||||
MSG("LESS: case -1: rebalancing")
|
||||
p1 = (*ppr)->tree_l;
|
||||
if (p1->tree_b == -1) { /* LL */
|
||||
MSG("LESS: single LL")
|
||||
(*ppr)->tree_l = p1->tree_r;
|
||||
p1->tree_r = *ppr;
|
||||
(*ppr)->tree_b = 0;
|
||||
*ppr = p1;
|
||||
}
|
||||
else { /* double LR */
|
||||
MSG("LESS: double LR")
|
||||
|
||||
p2 = p1->tree_r;
|
||||
p1->tree_r = p2->tree_l;
|
||||
p2->tree_l = p1;
|
||||
|
||||
(*ppr)->tree_l = p2->tree_r;
|
||||
p2->tree_r = *ppr;
|
||||
|
||||
if (p2->tree_b == -1)
|
||||
(*ppr)->tree_b = 1;
|
||||
else
|
||||
(*ppr)->tree_b = 0;
|
||||
|
||||
if (p2->tree_b == 1)
|
||||
p1->tree_b = -1;
|
||||
else
|
||||
p1->tree_b = 0;
|
||||
*ppr = p2;
|
||||
} /*else*/
|
||||
(*ppr)->tree_b = 0;
|
||||
*pi_balance = FALSE;
|
||||
} /*switch*/
|
||||
} /*if*/
|
||||
EXITV
|
||||
} /*if*/
|
||||
|
||||
/* if MORE, prepare to move to the right.
|
||||
*/
|
||||
if (cmp > 0) {
|
||||
MSG("MORE: sprouting to the right")
|
||||
sprout(&(*ppr)->tree_r, pc_data, pi_balance,
|
||||
pfi_compare, pfi_delete);
|
||||
if (*pi_balance) { /* right branch has grown longer */
|
||||
MSG("MORE: right branch has grown")
|
||||
|
||||
switch ((*ppr)->tree_b)
|
||||
{
|
||||
case -1:MSG("MORE: balance was off, fixed implicitly")
|
||||
(*ppr)->tree_b = 0;
|
||||
*pi_balance = FALSE;
|
||||
break;
|
||||
case 0: MSG("MORE: balance was okay, now off but ok")
|
||||
(*ppr)->tree_b = 1;
|
||||
break;
|
||||
case 1: MSG("MORE: balance was off, need to rebalance")
|
||||
p1 = (*ppr)->tree_r;
|
||||
if (p1->tree_b == 1) { /* RR */
|
||||
MSG("MORE: single RR")
|
||||
(*ppr)->tree_r = p1->tree_l;
|
||||
p1->tree_l = *ppr;
|
||||
(*ppr)->tree_b = 0;
|
||||
*ppr = p1;
|
||||
}
|
||||
else { /* double RL */
|
||||
MSG("MORE: double RL")
|
||||
|
||||
p2 = p1->tree_l;
|
||||
p1->tree_l = p2->tree_r;
|
||||
p2->tree_r = p1;
|
||||
|
||||
(*ppr)->tree_r = p2->tree_l;
|
||||
p2->tree_l = *ppr;
|
||||
|
||||
if (p2->tree_b == 1)
|
||||
(*ppr)->tree_b = -1;
|
||||
else
|
||||
(*ppr)->tree_b = 0;
|
||||
|
||||
if (p2->tree_b == -1)
|
||||
p1->tree_b = 1;
|
||||
else
|
||||
p1->tree_b = 0;
|
||||
|
||||
*ppr = p2;
|
||||
} /*else*/
|
||||
(*ppr)->tree_b = 0;
|
||||
*pi_balance = FALSE;
|
||||
} /*switch*/
|
||||
} /*if*/
|
||||
EXITV
|
||||
} /*if*/
|
||||
|
||||
/* not less, not more: this is the same key! replace...
|
||||
*/
|
||||
MSG("I found it! Replacing data value")
|
||||
*pi_balance = FALSE;
|
||||
if (pfi_delete)
|
||||
(*pfi_delete)((*ppr)->tree_p);
|
||||
(*ppr)->tree_p = pc_data;
|
||||
EXITV
|
||||
}
|
||||
|
||||
|
||||
int tree_delete(ppr_p, pfi_compare, pc_user, pfi_uar)
|
||||
tree **ppr_p;
|
||||
int (*pfi_compare)();
|
||||
char *pc_user;
|
||||
int (*pfi_uar)();
|
||||
{
|
||||
int i_balance = FALSE, i_uar_called = FALSE;
|
||||
|
||||
ENTER("tree_delete");
|
||||
EXIT(delete(ppr_p, pfi_compare, pc_user, pfi_uar,
|
||||
&i_balance, &i_uar_called))
|
||||
}
|
||||
|
||||
|
||||
static int delete(ppr_p, pfi_compare, pc_user, pfi_uar,
|
||||
pi_balance, pi_uar_called)
|
||||
tree **ppr_p;
|
||||
int (*pfi_compare)();
|
||||
char *pc_user;
|
||||
int (*pfi_uar)();
|
||||
int *pi_balance;
|
||||
int *pi_uar_called;
|
||||
{
|
||||
void del(), balanceL(), balanceR();
|
||||
tree *pr_q;
|
||||
int i_comp, i_ret;
|
||||
|
||||
ENTER("delete")
|
||||
|
||||
if (*ppr_p == NULL) {
|
||||
MSG("key not in tree")
|
||||
EXIT(FALSE)
|
||||
}
|
||||
|
||||
i_comp = (*pfi_compare)((*ppr_p)->tree_p, pc_user);
|
||||
if (i_comp > 0) {
|
||||
MSG("too high - scan left")
|
||||
i_ret = delete(&(*ppr_p)->tree_l, pfi_compare, pc_user, pfi_uar,
|
||||
pi_balance, pi_uar_called);
|
||||
if (*pi_balance)
|
||||
balanceL(ppr_p, pi_balance);
|
||||
}
|
||||
else if (i_comp < 0) {
|
||||
MSG("too low - scan right")
|
||||
i_ret = delete(&(*ppr_p)->tree_r, pfi_compare, pc_user, pfi_uar,
|
||||
pi_balance, pi_uar_called);
|
||||
if (*pi_balance)
|
||||
balanceR(ppr_p, pi_balance);
|
||||
}
|
||||
else {
|
||||
MSG("equal")
|
||||
pr_q = *ppr_p;
|
||||
if (pr_q->tree_r == NULL) {
|
||||
MSG("right subtree null")
|
||||
*ppr_p = pr_q->tree_l;
|
||||
*pi_balance = TRUE;
|
||||
}
|
||||
else if (pr_q->tree_l == NULL) {
|
||||
MSG("right subtree non-null, left subtree null")
|
||||
*ppr_p = pr_q->tree_r;
|
||||
*pi_balance = TRUE;
|
||||
}
|
||||
else {
|
||||
MSG("neither subtree null")
|
||||
del(&pr_q->tree_l, pi_balance, &pr_q, pfi_uar,
|
||||
pi_uar_called);
|
||||
if (*pi_balance)
|
||||
balanceL(ppr_p, pi_balance);
|
||||
}
|
||||
free(pr_q);
|
||||
if (!*pi_uar_called && *pfi_uar)
|
||||
(*pfi_uar)(pr_q->tree_p);
|
||||
i_ret = TRUE;
|
||||
}
|
||||
EXIT(i_ret)
|
||||
}
|
||||
|
||||
|
||||
static void del(ppr_r, pi_balance, ppr_q, pfi_uar, pi_uar_called)
|
||||
tree **ppr_r;
|
||||
int *pi_balance;
|
||||
tree **ppr_q;
|
||||
int (*pfi_uar)();
|
||||
int *pi_uar_called;
|
||||
{
|
||||
void balanceR();
|
||||
|
||||
ENTER("del")
|
||||
|
||||
if ((*ppr_r)->tree_r != NULL) {
|
||||
del(&(*ppr_r)->tree_r, pi_balance, ppr_q, pfi_uar,
|
||||
pi_uar_called);
|
||||
if (*pi_balance)
|
||||
balanceR(ppr_r, pi_balance);
|
||||
} else {
|
||||
if (pfi_uar)
|
||||
(*pfi_uar)((*ppr_q)->tree_p);
|
||||
*pi_uar_called = TRUE;
|
||||
(*ppr_q)->tree_p = (*ppr_r)->tree_p;
|
||||
*ppr_q = *ppr_r;
|
||||
*ppr_r = (*ppr_r)->tree_l;
|
||||
*pi_balance = TRUE;
|
||||
}
|
||||
|
||||
EXITV
|
||||
}
|
||||
|
||||
|
||||
static void balanceL(ppr_p, pi_balance)
|
||||
tree **ppr_p;
|
||||
int *pi_balance;
|
||||
{
|
||||
tree *p1, *p2;
|
||||
int b1, b2;
|
||||
|
||||
ENTER("balanceL")
|
||||
MSG("left branch has shrunk")
|
||||
|
||||
switch ((*ppr_p)->tree_b)
|
||||
{
|
||||
case -1: MSG("was imbalanced, fixed implicitly")
|
||||
(*ppr_p)->tree_b = 0;
|
||||
break;
|
||||
case 0: MSG("was okay, is now one off")
|
||||
(*ppr_p)->tree_b = 1;
|
||||
*pi_balance = FALSE;
|
||||
break;
|
||||
case 1: MSG("was already off, this is too much")
|
||||
p1 = (*ppr_p)->tree_r;
|
||||
b1 = p1->tree_b;
|
||||
if (b1 >= 0) {
|
||||
MSG("single RR")
|
||||
(*ppr_p)->tree_r = p1->tree_l;
|
||||
p1->tree_l = *ppr_p;
|
||||
if (b1 == 0) {
|
||||
MSG("b1 == 0")
|
||||
(*ppr_p)->tree_b = 1;
|
||||
p1->tree_b = -1;
|
||||
*pi_balance = FALSE;
|
||||
} else {
|
||||
MSG("b1 != 0")
|
||||
(*ppr_p)->tree_b = 0;
|
||||
p1->tree_b = 0;
|
||||
}
|
||||
*ppr_p = p1;
|
||||
} else {
|
||||
MSG("double RL")
|
||||
p2 = p1->tree_l;
|
||||
b2 = p2->tree_b;
|
||||
p1->tree_l = p2->tree_r;
|
||||
p2->tree_r = p1;
|
||||
(*ppr_p)->tree_r = p2->tree_l;
|
||||
p2->tree_l = *ppr_p;
|
||||
if (b2 == 1)
|
||||
(*ppr_p)->tree_b = -1;
|
||||
else
|
||||
(*ppr_p)->tree_b = 0;
|
||||
if (b2 == -1)
|
||||
p1->tree_b = 1;
|
||||
else
|
||||
p1->tree_b = 0;
|
||||
*ppr_p = p2;
|
||||
p2->tree_b = 0;
|
||||
}
|
||||
}
|
||||
EXITV
|
||||
}
|
||||
|
||||
|
||||
static void balanceR(ppr_p, pi_balance)
|
||||
tree **ppr_p;
|
||||
int *pi_balance;
|
||||
{
|
||||
tree *p1, *p2;
|
||||
int b1, b2;
|
||||
|
||||
ENTER("balanceR")
|
||||
MSG("right branch has shrunk")
|
||||
switch ((*ppr_p)->tree_b)
|
||||
{
|
||||
case 1: MSG("was imbalanced, fixed implicitly")
|
||||
(*ppr_p)->tree_b = 0;
|
||||
break;
|
||||
case 0: MSG("was okay, is now one off")
|
||||
(*ppr_p)->tree_b = -1;
|
||||
*pi_balance = FALSE;
|
||||
break;
|
||||
case -1: MSG("was already off, this is too much")
|
||||
p1 = (*ppr_p)->tree_l;
|
||||
b1 = p1->tree_b;
|
||||
if (b1 <= 0) {
|
||||
MSG("single LL")
|
||||
(*ppr_p)->tree_l = p1->tree_r;
|
||||
p1->tree_r = *ppr_p;
|
||||
if (b1 == 0) {
|
||||
MSG("b1 == 0")
|
||||
(*ppr_p)->tree_b = -1;
|
||||
p1->tree_b = 1;
|
||||
*pi_balance = FALSE;
|
||||
} else {
|
||||
MSG("b1 != 0")
|
||||
(*ppr_p)->tree_b = 0;
|
||||
p1->tree_b = 0;
|
||||
}
|
||||
*ppr_p = p1;
|
||||
} else {
|
||||
MSG("double LR")
|
||||
p2 = p1->tree_r;
|
||||
b2 = p2->tree_b;
|
||||
p1->tree_r = p2->tree_l;
|
||||
p2->tree_l = p1;
|
||||
(*ppr_p)->tree_l = p2->tree_r;
|
||||
p2->tree_r = *ppr_p;
|
||||
if (b2 == -1)
|
||||
(*ppr_p)->tree_b = 1;
|
||||
else
|
||||
(*ppr_p)->tree_b = 0;
|
||||
if (b2 == 1)
|
||||
p1->tree_b = -1;
|
||||
else
|
||||
p1->tree_b = 0;
|
||||
*ppr_p = p2;
|
||||
p2->tree_b = 0;
|
||||
}
|
||||
}
|
||||
EXITV
|
||||
}
|
||||
|
||||
|
||||
int tree_trav(ppr_tree, pfi_uar)
|
||||
tree **ppr_tree;
|
||||
int (*pfi_uar)();
|
||||
{
|
||||
ENTER("tree_trav")
|
||||
|
||||
if (!*ppr_tree)
|
||||
EXIT(TRUE)
|
||||
|
||||
if (!tree_trav(&(**ppr_tree).tree_l, pfi_uar))
|
||||
EXIT(FALSE)
|
||||
if (!(*pfi_uar)((**ppr_tree).tree_p))
|
||||
EXIT(FALSE)
|
||||
if (!tree_trav(&(**ppr_tree).tree_r, pfi_uar))
|
||||
EXIT(FALSE)
|
||||
EXIT(TRUE)
|
||||
}
|
||||
|
||||
|
||||
void tree_mung(ppr_tree, pfi_uar)
|
||||
tree **ppr_tree;
|
||||
int (*pfi_uar)();
|
||||
{
|
||||
ENTER("tree_mung")
|
||||
if (*ppr_tree)
|
||||
{
|
||||
tree_mung(&(**ppr_tree).tree_l, pfi_uar);
|
||||
tree_mung(&(**ppr_tree).tree_r, pfi_uar);
|
||||
if (pfi_uar)
|
||||
(*pfi_uar)((**ppr_tree).tree_p);
|
||||
free(*ppr_tree);
|
||||
*ppr_tree = NULL;
|
||||
}
|
||||
EXITV
|
||||
}
|
||||
19
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/avl-subs/tree.h
Normal file
19
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/avl-subs/tree.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/* tree.h - declare structures used by tree.c
|
||||
* vix 27jun86 [broken out of tree.c]
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _TREE_FLAG
|
||||
#define _TREE_FLAG
|
||||
|
||||
|
||||
typedef struct tree_s
|
||||
{
|
||||
struct tree_s *tree_l, *tree_r;
|
||||
short tree_b;
|
||||
char *tree_p;
|
||||
}
|
||||
tree;
|
||||
|
||||
|
||||
#endif _TREE_FLAG
|
||||
124
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/avl-subs/tree.man3
Normal file
124
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/avl-subs/tree.man3
Normal file
@@ -0,0 +1,124 @@
|
||||
.TH TREE 2 "23 June 1986"
|
||||
.UC 4
|
||||
.SH NAME
|
||||
tree_init, tree_mung, tree_srch, tree_add, tree_delete, tree_trav \- balanced binary tree routines
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
.B void
|
||||
.B tree_init(tree)
|
||||
.B int **tree;
|
||||
.PP
|
||||
.B int *
|
||||
.B tree_srch(tree, compare, data)
|
||||
.B int **tree, (*compare)(), *data;
|
||||
.PP
|
||||
.B void
|
||||
.B tree_add(tree, compare, data, del_uar)
|
||||
.B int **tree, (*compare)(), *data, (*del_uar)();
|
||||
.PP
|
||||
.B int
|
||||
.B tree_delete(tree, compare, data, del_uar)
|
||||
.B int **tree, (*compare)(), *data, (*del_uar)();
|
||||
.PP
|
||||
.B int
|
||||
.B tree_trav(tree, trav_uar)
|
||||
.B int **tree, (*trav_uar)();
|
||||
.PP
|
||||
.B void
|
||||
.B tree_mung(tree, del_uar)
|
||||
.B int **tree, (*del_uar)();
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
These functions create and manipulate a balanced binary (AVL) tree. Each node
|
||||
of the tree contains the expected left & right subtree pointers, a short-int
|
||||
balance indicator, and a pointer to the user-data. On a 32-bit system, this
|
||||
means an overhead of 4+4+2+4 bytes per node. There is no key data type
|
||||
enforced by this package; a caller-supplied compare routine is used to compare
|
||||
user-data blocks.
|
||||
.PP
|
||||
.I Tree_init
|
||||
creates an empty tree and binds it to
|
||||
.I tree
|
||||
(which for this and all other routines in this package should be declared as
|
||||
a pointer to integer and passed by reference), which can then be used by other
|
||||
routines in this package. Note that more than one
|
||||
.I tree
|
||||
variable can exist at once; thus multiple trees can be manipulated
|
||||
simultaneously.
|
||||
.PP
|
||||
.I Tree_srch
|
||||
searches a tree for a specific node and returns either
|
||||
.I NULL
|
||||
if no node was found, or the address of the user-data for that node if one was
|
||||
found.
|
||||
.I compare
|
||||
is the address of a function to compare two user-data blocks. This routine
|
||||
should work much the way
|
||||
.IR strcmp 2
|
||||
does; in fact,
|
||||
.I strcmp
|
||||
could be used if the user-data was a null-terminated string.
|
||||
.I data
|
||||
is the address of a user-data block to be used via
|
||||
.I compare
|
||||
as the search criteria. The tree is searched for a node where
|
||||
.I compare
|
||||
returns 0.
|
||||
.PP
|
||||
.I Tree_add
|
||||
inserts or replaces a node in the specified tree. The tree specified by
|
||||
.I tree
|
||||
is searched as in
|
||||
.I tree_srch,
|
||||
and if a node is found to match
|
||||
.I data,
|
||||
then the
|
||||
.I del_uar
|
||||
function is called with the address of the user-data block for the node
|
||||
(this routine should deallocate any dynamic memory which is pointed to
|
||||
exclusively by the node); the user-data pointer for the node is then
|
||||
replaced by the value of
|
||||
.I data.
|
||||
If no node is found to match, a new node is added (which may or may not
|
||||
cause a transparent rebalance operation), with a user-data pointer equal
|
||||
to
|
||||
.I data.
|
||||
.PP
|
||||
.I Tree_delete
|
||||
deletes a node from
|
||||
.I tree.
|
||||
A rebalance may or may not occur, depending on where the node is removed from
|
||||
and what the rest of the tree looks like.
|
||||
.I Tree_delete
|
||||
returns TRUE if a node was deleted, FALSE otherwise.
|
||||
.PP
|
||||
.I Tree_trav
|
||||
traverses all of
|
||||
.I tree,
|
||||
calling
|
||||
.I trav_uar
|
||||
with the address of each user-data block. If
|
||||
.I trav_uar
|
||||
returns FALSE at any time,
|
||||
.I tree_trav
|
||||
will immediately return FALSE to its caller. Otherwise all nodes will be
|
||||
reached and
|
||||
.I tree_trav
|
||||
will return TRUE.
|
||||
.PP
|
||||
.I Tree_mung
|
||||
deletes every node in
|
||||
.I tree,
|
||||
calling
|
||||
.I del_uar
|
||||
with the user-data address from each node (see
|
||||
.I tree_add
|
||||
and
|
||||
.I tree_delete
|
||||
above). The tree is left in the same state that
|
||||
.I tree_init
|
||||
leaves it in \- i.e., empty.
|
||||
.SH AUTHOR
|
||||
Paul Vixie, converted and augumented from Modula-2 examples in
|
||||
.I Algorithms & Data Structures,
|
||||
Niklaus Wirth, Prentice-Hall, ISBN 0-13-022005-1.
|
||||
73
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/avl-subs/vixie.h
Normal file
73
ASSEMBLY & COMPILE TOOLS/PLM-2-C 2/avl-subs/vixie.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/* vixie.h - include file to define general vixie-type things
|
||||
* v1.0 vix 21jun86 [broken out of as.h]
|
||||
*/
|
||||
|
||||
#ifdef DOCUMENTATION
|
||||
|
||||
There are two macros you can define before including this file which can
|
||||
change the things defined by this file.
|
||||
|
||||
DEBUG: if defined, will cause enter/exit messages to be printed by the
|
||||
ENTER/EXIT/EXITV macros. If not defined, causes ENTER to do nothing,
|
||||
and EXIT/EXITV to generate 'return' without any messages.
|
||||
|
||||
If defined, should be set to the name of the including module.
|
||||
|
||||
MAIN: Should be defined for a program containing a main() function which
|
||||
is linked with other modules which include this file.
|
||||
|
||||
Value is not important, only existence/nonexistence matters.
|
||||
|
||||
#endif DOCUMENTATION
|
||||
|
||||
|
||||
#ifndef _VIXIE_FLAG
|
||||
#define _VIXIE_FLAG
|
||||
|
||||
|
||||
/*--- debugging stuff ---*/
|
||||
#define MAXPROC 256
|
||||
|
||||
#ifdef DEBUG
|
||||
#define ENTER(proc) { \
|
||||
APC_PROCS[I_PROC] = proc; \
|
||||
printf("ENTER(%d:%s.%s)\n", \
|
||||
I_PROC, DEBUG, APC_PROCS[I_PROC]); \
|
||||
I_PROC++; \
|
||||
}
|
||||
#define EXIT(value) { \
|
||||
I_PROC--; \
|
||||
printf("EXIT(%d:%s.%s)\n", \
|
||||
I_PROC, DEBUG, \
|
||||
APC_PROCS[I_PROC]); \
|
||||
return value; \
|
||||
}
|
||||
#define EXITV { \
|
||||
I_PROC--; \
|
||||
printf("EXITV(%d:%s.%s)\n", \
|
||||
I_PROC, DEBUG, \
|
||||
APC_PROCS[I_PROC]); \
|
||||
return value; \
|
||||
}
|
||||
#else
|
||||
#define ENTER(proc)
|
||||
#define EXIT(value) {return value;}
|
||||
#define EXITV return;
|
||||
#endif
|
||||
|
||||
#ifdef MAIN
|
||||
int I_PROC = 0;
|
||||
char *APC_PROCS[MAXPROC];
|
||||
#else
|
||||
extern int I_PROC;
|
||||
extern char *APC_PROCS[MAXPROC];
|
||||
#endif
|
||||
|
||||
|
||||
/*--- why didn't k&r put these into stdio.h? ---*/
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
extern char *malloc(), *calloc();
|
||||
|
||||
|
||||
#endif _VIXIE_FLAG
|
||||
Reference in New Issue
Block a user