home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume11 / avl-subs next >
Text File  |  1987-08-27  |  24KB  |  1,012 lines

  1. Path: uunet!rs
  2. From: rs@uunet.UU.NET (Rich Salz)
  3. Newsgroups: comp.sources.unix
  4. Subject: v11i020:  AVL Tree subroutines
  5. Message-ID: <1244@uunet.UU.NET>
  6. Date: 28 Aug 87 13:00:46 GMT
  7. Organization: UUNET Communications Services, Arlington, VA
  8. Lines: 1001
  9. Approved: rs@uunet.UU.NET
  10.  
  11. Submitted-by: vixie!paul@uunet.UU.NET (Paul Vixie Esq)
  12. Posting-number: Volume 11, Issue 20
  13. Archive-name: avl-subs
  14.  
  15. Here's an AVL tree library, written in C.  Someone asked about it on
  16. comp.sources.wanted; I'll send him a copy too, but I think it's of
  17. general utility, so I'd like to see it in comp.sources.unix.  It's known
  18. to run on my Symmetric, and on a Macintosh (!) with the DeSmet C Compiler.
  19.  
  20. I extracted it from a PD assembler I was writing a year or so back, so
  21. it makes some references to "as" in some comments... Please ignore these...
  22.  
  23. #! /bin/sh
  24. ##  This is a shell archive.  Remove anything before this line, then unpack
  25. ##  it by saving it into a file and typing "sh file".  To overwrite existing
  26. ##  files, type "sh file -c".  You can also feed this as standard input via
  27. ##  unshar, or by typing "sh <file".  If this archive is complete, you will
  28. ##  see the following message at the end:
  29. #        "End of shell archive."
  30. # Contents:  Makefile README t_trtest.c tree.c tree.h tree.man3 vixie.h
  31. # Wrapped by paul@vixie on Fri Jul 24 10:35:46 1987
  32. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  33. if test -f Makefile -a "${1}" != "-c" ; then 
  34.   echo shar: Will not over-write existing file \"Makefile\"
  35. else
  36. echo shar: Extracting \"Makefile\" \(331 characters\)
  37. sed "s/^X//" >Makefile <<'END_OF_Makefile'
  38. X# makefile for tree stuff
  39. X# vix 24jul87 [stripped down from as makefile]
  40. X
  41. XCFLAGS        =    -O
  42. X
  43. XTRTEST_OBJ    =    t_trtest.o tree.o
  44. X
  45. Xall        :    t_trtest
  46. X
  47. Xt_trtest    :    $(TRTEST_OBJ)
  48. X            cc -o t_trtest $(TRTEST_OBJ)
  49. X
  50. Xclean        :    FRC
  51. X            rm -f core a.out t_trtest $(TRTEST_OBJ)
  52. X
  53. XFRC        :
  54. X
  55. Xtree.o        :    tree.c tree.h vixie.h
  56. Xt_trtest.o    :    t_trtest.c tree.h vixie.h
  57. END_OF_Makefile
  58. if test 331 -ne `wc -c <Makefile`; then
  59.     echo shar: \"Makefile\" unpacked with wrong size!
  60. fi
  61. # end of overwriting check
  62. fi
  63. if test -f README -a "${1}" != "-c" ; then 
  64.   echo shar: Will not over-write existing file \"README\"
  65. else
  66. echo shar: Extracting \"README\" \(1286 characters\)
  67. sed "s/^X//" >README <<'END_OF_README'
  68. XAVL Trees V1.0
  69. X24-July-1987
  70. XPaul Vixie
  71. X
  72. XThis library and test program are useful for creating and using balanced
  73. Xbinary trees (AVL trees).  The tree is held in memory, using malloc(3) to
  74. Xallocate storage.  A better version would allow file-based trees in 
  75. Xaddition; once memory mapped files hit the UNIX(tm) community, this will
  76. Xbe much easier to do.  In the meanwhile, these routines have been very
  77. Xuseful to be for symbol tables and the like.  (Yes, I'm sure hashing is
  78. Xbetter in some way, but I've used this for symbol tables, just the same.)
  79. X
  80. XI cannot take credit for the algorithms.  See "Algorithms & Data Structures,"
  81. XNiklaus Wirth, Prentice-Hall 1986, ISBN 0-13-022005-1.  This is an update of
  82. XWirth's previous book, titled "Algorythms + Data Structures = Programs,"
  83. Xwhich used Pascal as the language for examples.  This later book uses the
  84. Xnewer Modula-2 for it's examples; this tree code was created using the
  85. XModula-2 examples as guidelines.  At the time I typed this stuff in (about
  86. Xa year ago, in July 1987), I understood how it all worked.  Today, well...
  87. X
  88. XThis code is hereby placed in the public domain, unless restrictions apply
  89. Xfrom Prentice-Hall on the algorithms themselves.  If you use or redistribute
  90. Xthis code, please leave my name (and Wirth's) in the comments.
  91. END_OF_README
  92. if test 1286 -ne `wc -c <README`; then
  93.     echo shar: \"README\" unpacked with wrong size!
  94. fi
  95. # end of overwriting check
  96. fi
  97. if test -f t_trtest.c -a "${1}" != "-c" ; then 
  98.   echo shar: Will not over-write existing file \"t_trtest.c\"
  99. else
  100. echo shar: Extracting \"t_trtest.c\" \(1912 characters\)
  101. sed "s/^X//" >t_trtest.c <<'END_OF_t_trtest.c'
  102. X/* t_trtest - test the tree functions
  103. X * vix 24jul87 [documented, added savestr for net distribution]
  104. X */
  105. X
  106. X#define MAIN
  107. X
  108. X#include <stdio.h>
  109. X#include "vixie.h"
  110. X#include "tree.h"
  111. X
  112. Xmain()
  113. X{
  114. X    tree    *t;
  115. X    char    line[100];
  116. X
  117. X    tree_init(&t);
  118. X    while (printf("line (or .):  "), gets(line), line[0] != '.')
  119. X    {
  120. X        if (strncmp(line, "~r ", 3)) {
  121. X            trtest(&t, line, 1);
  122. X        }
  123. X        else {
  124. X            FILE *f;
  125. X
  126. X            if (!(f = fopen(&line[3], "r")))
  127. X                perror(&line[3]);
  128. X            else {
  129. X                while (fgets(line, 100, f)) {
  130. X                    line[strlen(line)-1] = '\0';
  131. X                    printf("(%s)\n", line);
  132. X                    trtest(&t, line, 0);
  133. X                }
  134. X                fclose(f);
  135. X            }
  136. X        }
  137. X    }
  138. X}
  139. X
  140. Xtrtest(tt, line, inter)
  141. Xtree    **tt;
  142. Xchar    *line;
  143. X{
  144. X    char    opts[100], *tree_srch(), *pc, *n;
  145. X    int    uar_print(), duar(), compar(), opt, status;
  146. X
  147. X    pc = tree_srch(tt, compar, line);
  148. X    printf("tree_srch=%08lx\n", pc);
  149. X    if (pc)
  150. X    {
  151. X        printf("     <%s>\n", pc);
  152. X
  153. X        if (inter) {
  154. X            printf("delete? "); gets(opts); opt = (opts[0]=='y');
  155. X        }
  156. X        else
  157. X            opt = 1;
  158. X
  159. X        if (opt) {
  160. X            status = tree_delete(tt, compar, line, duar);
  161. X            printf("delete=%d\n", status);
  162. X        }
  163. X    }
  164. X    else
  165. X    {
  166. X        if (inter) {
  167. X            printf("add? "); gets(opts); opt = (opts[0]=='y');
  168. X        }
  169. X        else
  170. X            opt = 1;
  171. X
  172. X        if (opt) {
  173. X            char    *savestr();
  174. X
  175. X            n = savestr(line);
  176. X            tree_add(tt, compar, n, duar);
  177. X        }
  178. X    }
  179. X    tree_trav1(*tt, 0);
  180. X}
  181. X
  182. Xduar(pc)
  183. Xchar *pc;
  184. X{
  185. X    printf("duar called, pc=%08X: <%s>\n", pc, pc?pc:"");
  186. X    free(pc);
  187. X}
  188. X
  189. Xtree_trav1(t, l)
  190. Xtree    *t;
  191. X{
  192. X    int    i;
  193. X
  194. X    if (!t) return;
  195. X    tree_trav1(t->tree_l, l+1);
  196. X    for (i=0;  i<l;  i++) printf("  ");
  197. X    printf("%08lx (%s)\n", t->tree_p, t->tree_p);
  198. X    tree_trav1(t->tree_r, l+1);
  199. X}    
  200. X    
  201. Xuar_print(pc)
  202. Xchar    *pc;
  203. X{
  204. X    printf("uar_print(%08lx)", pc);
  205. X    if (pc)
  206. X        printf(" '%s'", pc);
  207. X    putchar('\n');
  208. X    return 1;
  209. X}
  210. X
  211. Xcompar(l, r)
  212. X    char *l, *r;
  213. X{
  214. X    printf("compar(%s,%s)=%d\n", l, r, strcmp(l, r));
  215. X    return strcmp(l, r);
  216. X}
  217. X
  218. Xchar *
  219. Xsavestr(str)
  220. X    char    *str;
  221. X{
  222. X    char    *save;
  223. X
  224. X    save = malloc(strlen(str) + 1);
  225. X    strcpy(save, str);
  226. X    return save;
  227. X}
  228. END_OF_t_trtest.c
  229. if test 1912 -ne `wc -c <t_trtest.c`; then
  230.     echo shar: \"t_trtest.c\" unpacked with wrong size!
  231. fi
  232. # end of overwriting check
  233. fi
  234. if test -f tree.c -a "${1}" != "-c" ; then 
  235.   echo shar: Will not over-write existing file \"tree.c\"
  236. else
  237. echo shar: Extracting \"tree.c\" \(10313 characters\)
  238. sed "s/^X//" >tree.c <<'END_OF_tree.c'
  239. X/* as_tree - tree library for as
  240. X * vix 14dec85 [written]
  241. X * vix 02feb86 [added tree balancing from wirth "a+ds=p" p. 220-221]
  242. X * vix 06feb86 [added tree_mung()]
  243. X * vix 20jun86 [added tree_delete per wirth a+ds (mod2 v.) p. 224]
  244. X * vix 23jun86 [added delete uar to add for replaced nodes]
  245. X */
  246. X
  247. X
  248. X/* This program text was created by Paul Vixie using examples from the book:
  249. X * "Algorithms & Data Structures," Niklaus Wirth, Prentice-Hall, 1986, ISBN
  250. X * 0-13-022005-1.  This code and associated documentation is hereby placed
  251. X * in the public domain.
  252. X */
  253. X
  254. X
  255. X/*#define        DEBUG    "tree"*/
  256. X
  257. X
  258. X#include <stdio.h>
  259. X#include "vixie.h"
  260. X#include "tree.h"
  261. X
  262. X
  263. X#ifdef DEBUG
  264. X#define        MSG(msg)    printf("DEBUG: '%s'\n", msg);
  265. X#else
  266. X#define        MSG(msg)
  267. X#endif
  268. X
  269. X
  270. Xvoid tree_init(ppr_tree)
  271. Xtree    **ppr_tree;
  272. X{
  273. X    ENTER("tree_init")
  274. X    *ppr_tree = NULL;
  275. X    EXITV
  276. X}
  277. X    
  278. X
  279. Xchar *tree_srch(ppr_tree, pfi_compare, pc_user)
  280. Xtree    **ppr_tree;
  281. Xint    (*pfi_compare)();
  282. Xchar    *pc_user;
  283. X{
  284. X    register int    i_comp;
  285. X    register tree    *pr_new;
  286. X
  287. X    ENTER("tree_srch")
  288. X
  289. X    if (*ppr_tree)
  290. X    {
  291. X        i_comp = (*pfi_compare)(pc_user, (**ppr_tree).tree_p);
  292. X        if (i_comp > 0)
  293. X            EXIT(tree_srch(
  294. X                &(**ppr_tree).tree_r,
  295. X                pfi_compare,
  296. X                pc_user
  297. X            ))
  298. X        if (i_comp < 0)
  299. X            EXIT(tree_srch(
  300. X                &(**ppr_tree).tree_l,
  301. X                pfi_compare,
  302. X                pc_user
  303. X            ))
  304. X
  305. X        /* not higher, not lower... this must be the one.
  306. X         */
  307. X        EXIT((**ppr_tree).tree_p)
  308. X    }
  309. X
  310. X    /* grounded. NOT found.
  311. X     */
  312. X    EXIT(NULL)
  313. X}
  314. X
  315. X
  316. Xvoid tree_add(ppr_tree, pfi_compare, pc_user, pfi_delete)
  317. Xtree    **ppr_tree;
  318. Xint    (*pfi_compare)();
  319. Xchar    *pc_user;
  320. Xint    (*pfi_delete)();
  321. X{
  322. X    void    sprout();
  323. X    int    i_balance = FALSE;
  324. X
  325. X    ENTER("tree_add")
  326. X    sprout(ppr_tree, pc_user, &i_balance, pfi_compare, pfi_delete);
  327. X    EXITV
  328. X}
  329. X
  330. X
  331. Xstatic void sprout(ppr, pc_data, pi_balance, pfi_compare, pfi_delete)
  332. Xtree    **ppr;
  333. Xchar    *pc_data;
  334. Xint    *pi_balance;
  335. Xint    (*pfi_compare)();
  336. Xint    (*pfi_delete)();
  337. X{
  338. X    tree    *p1, *p2;
  339. X    int    cmp;
  340. X
  341. X    ENTER("sprout")
  342. X
  343. X    /* are we grounded?  if so, add the node "here" and set the rebalance
  344. X     * flag, then exit.
  345. X     */
  346. X    if (!*ppr) {
  347. X        MSG("grounded. adding new node, setting h=true")
  348. X        *ppr = (tree *) malloc(sizeof(tree));
  349. X        (*ppr)->tree_l = NULL;
  350. X        (*ppr)->tree_r = NULL;
  351. X        (*ppr)->tree_b = 0;
  352. X        (*ppr)->tree_p = pc_data;
  353. X        *pi_balance = TRUE;
  354. X        EXITV
  355. X    }
  356. X
  357. X    /* compare the data using routine passed by caller.
  358. X     */
  359. X    cmp = (*pfi_compare)(pc_data, (*ppr)->tree_p);
  360. X
  361. X    /* if LESS, prepare to move to the left.
  362. X     */
  363. X    if (cmp < 0) {
  364. X        MSG("LESS. sprouting left.")
  365. X        sprout(&(*ppr)->tree_l, pc_data, pi_balance,
  366. X            pfi_compare, pfi_delete);
  367. X        if (*pi_balance) {    /* left branch has grown longer */
  368. X            MSG("LESS: left branch has grown")
  369. X            switch ((*ppr)->tree_b)
  370. X            {
  371. X            case 1:    /* right branch WAS longer; balance is ok now */
  372. X                MSG("LESS: case 1.. balnce restored implicitly")
  373. X                (*ppr)->tree_b = 0;
  374. X                *pi_balance = FALSE;
  375. X                break;
  376. X            case 0:    /* balance WAS okay; now left branch longer */
  377. X                MSG("LESS: case 0.. balnce bad but still ok")
  378. X                (*ppr)->tree_b = -1;
  379. X                break;
  380. X            case -1:
  381. X                /* left branch was already too long. rebalnce */
  382. X                MSG("LESS: case -1: rebalancing")
  383. X                p1 = (*ppr)->tree_l;
  384. X                if (p1->tree_b == -1) {    /* LL */
  385. X                    MSG("LESS: single LL")
  386. X                    (*ppr)->tree_l = p1->tree_r;
  387. X                    p1->tree_r = *ppr;
  388. X                    (*ppr)->tree_b = 0;
  389. X                    *ppr = p1;
  390. X                }
  391. X                else {            /* double LR */
  392. X                    MSG("LESS: double LR")
  393. X
  394. X                    p2 = p1->tree_r;
  395. X                    p1->tree_r = p2->tree_l;
  396. X                    p2->tree_l = p1;
  397. X
  398. X                    (*ppr)->tree_l = p2->tree_r;
  399. X                    p2->tree_r = *ppr;
  400. X
  401. X                    if (p2->tree_b == -1)
  402. X                        (*ppr)->tree_b = 1;
  403. X                    else
  404. X                        (*ppr)->tree_b = 0;
  405. X
  406. X                    if (p2->tree_b == 1)
  407. X                        p1->tree_b = -1;
  408. X                    else
  409. X                        p1->tree_b = 0;
  410. X                    *ppr = p2;
  411. X                } /*else*/
  412. X                (*ppr)->tree_b = 0;
  413. X                *pi_balance = FALSE;
  414. X            } /*switch*/
  415. X        } /*if*/
  416. X        EXITV
  417. X    } /*if*/
  418. X
  419. X    /* if MORE, prepare to move to the right.
  420. X     */
  421. X    if (cmp > 0) {
  422. X        MSG("MORE: sprouting to the right")
  423. X        sprout(&(*ppr)->tree_r, pc_data, pi_balance,
  424. X            pfi_compare, pfi_delete);
  425. X        if (*pi_balance) {    /* right branch has grown longer */
  426. X            MSG("MORE: right branch has grown")
  427. X
  428. X            switch ((*ppr)->tree_b)
  429. X            {
  430. X            case -1:MSG("MORE: balance was off, fixed implicitly")
  431. X                (*ppr)->tree_b = 0;
  432. X                *pi_balance = FALSE;
  433. X                break;
  434. X            case 0:    MSG("MORE: balance was okay, now off but ok")
  435. X                (*ppr)->tree_b = 1;
  436. X                break;
  437. X            case 1:    MSG("MORE: balance was off, need to rebalance")
  438. X                p1 = (*ppr)->tree_r;
  439. X                if (p1->tree_b == 1) {    /* RR */
  440. X                    MSG("MORE: single RR")
  441. X                    (*ppr)->tree_r = p1->tree_l;
  442. X                    p1->tree_l = *ppr;
  443. X                    (*ppr)->tree_b = 0;
  444. X                    *ppr = p1;
  445. X                }
  446. X                else {            /* double RL */
  447. X                    MSG("MORE: double RL")
  448. X
  449. X                    p2 = p1->tree_l;
  450. X                    p1->tree_l = p2->tree_r;
  451. X                    p2->tree_r = p1;
  452. X
  453. X                    (*ppr)->tree_r = p2->tree_l;
  454. X                    p2->tree_l = *ppr;
  455. X
  456. X                    if (p2->tree_b == 1)
  457. X                        (*ppr)->tree_b = -1;
  458. X                    else
  459. X                        (*ppr)->tree_b = 0;
  460. X
  461. X                    if (p2->tree_b == -1)
  462. X                        p1->tree_b = 1;
  463. X                    else
  464. X                        p1->tree_b = 0;
  465. X
  466. X                    *ppr = p2;
  467. X                } /*else*/
  468. X                (*ppr)->tree_b = 0;
  469. X                *pi_balance = FALSE;
  470. X            } /*switch*/
  471. X        } /*if*/
  472. X        EXITV
  473. X    } /*if*/
  474. X
  475. X    /* not less, not more: this is the same key!  replace...
  476. X     */
  477. X    MSG("I found it!  Replacing data value")
  478. X    *pi_balance = FALSE;
  479. X    if (pfi_delete)
  480. X        (*pfi_delete)((*ppr)->tree_p);
  481. X    (*ppr)->tree_p = pc_data;
  482. X    EXITV
  483. X}
  484. X
  485. X
  486. Xint tree_delete(ppr_p, pfi_compare, pc_user, pfi_uar)
  487. Xtree    **ppr_p;
  488. Xint    (*pfi_compare)();
  489. Xchar    *pc_user;
  490. Xint    (*pfi_uar)();
  491. X{
  492. X    int    i_balance = FALSE, i_uar_called = FALSE;
  493. X
  494. X    ENTER("tree_delete");
  495. X    EXIT(delete(ppr_p, pfi_compare, pc_user, pfi_uar,
  496. X                &i_balance, &i_uar_called))
  497. X}
  498. X
  499. X
  500. Xstatic int delete(ppr_p, pfi_compare, pc_user, pfi_uar,
  501. X                        pi_balance, pi_uar_called)
  502. Xtree    **ppr_p;
  503. Xint    (*pfi_compare)();
  504. Xchar    *pc_user;
  505. Xint    (*pfi_uar)();
  506. Xint    *pi_balance;
  507. Xint    *pi_uar_called;
  508. X{
  509. X    void    del(), balanceL(), balanceR();
  510. X    tree    *pr_q;
  511. X    int    i_comp, i_ret;
  512. X
  513. X    ENTER("delete")
  514. X
  515. X    if (*ppr_p == NULL) {
  516. X        MSG("key not in tree")
  517. X        EXIT(FALSE)
  518. X    }
  519. X
  520. X    i_comp = (*pfi_compare)((*ppr_p)->tree_p, pc_user);
  521. X    if (i_comp > 0) {
  522. X        MSG("too high - scan left")
  523. X        i_ret = delete(&(*ppr_p)->tree_l, pfi_compare, pc_user, pfi_uar,
  524. X                        pi_balance, pi_uar_called);
  525. X        if (*pi_balance)
  526. X            balanceL(ppr_p, pi_balance);
  527. X    }
  528. X    else if (i_comp < 0) {
  529. X        MSG("too low - scan right")
  530. X        i_ret = delete(&(*ppr_p)->tree_r, pfi_compare, pc_user, pfi_uar,
  531. X                        pi_balance, pi_uar_called);
  532. X        if (*pi_balance)
  533. X            balanceR(ppr_p, pi_balance);
  534. X    }
  535. X    else {
  536. X        MSG("equal")
  537. X        pr_q = *ppr_p;
  538. X        if (pr_q->tree_r == NULL) {
  539. X            MSG("right subtree null")
  540. X            *ppr_p = pr_q->tree_l;
  541. X            *pi_balance = TRUE;
  542. X        }
  543. X        else if (pr_q->tree_l == NULL) {
  544. X            MSG("right subtree non-null, left subtree null")
  545. X            *ppr_p = pr_q->tree_r;
  546. X            *pi_balance = TRUE;
  547. X        }
  548. X        else {
  549. X            MSG("neither subtree null")
  550. X            del(&pr_q->tree_l, pi_balance, &pr_q, pfi_uar,
  551. X                                pi_uar_called);
  552. X            if (*pi_balance)
  553. X                balanceL(ppr_p, pi_balance);
  554. X        }
  555. X        free(pr_q);
  556. X        if (!*pi_uar_called && *pfi_uar)
  557. X            (*pfi_uar)(pr_q->tree_p);
  558. X        i_ret = TRUE;
  559. X    }
  560. X    EXIT(i_ret)
  561. X}
  562. X
  563. X
  564. Xstatic void del(ppr_r, pi_balance, ppr_q, pfi_uar, pi_uar_called)
  565. Xtree    **ppr_r;
  566. Xint    *pi_balance;
  567. Xtree    **ppr_q;
  568. Xint    (*pfi_uar)();
  569. Xint    *pi_uar_called;
  570. X{
  571. X    void    balanceR();
  572. X
  573. X    ENTER("del")
  574. X
  575. X    if ((*ppr_r)->tree_r != NULL) {
  576. X        del(&(*ppr_r)->tree_r, pi_balance, ppr_q, pfi_uar,
  577. X                                pi_uar_called);
  578. X        if (*pi_balance)
  579. X            balanceR(ppr_r, pi_balance);
  580. X    } else {
  581. X        if (pfi_uar)
  582. X            (*pfi_uar)((*ppr_q)->tree_p);
  583. X        *pi_uar_called = TRUE;
  584. X        (*ppr_q)->tree_p = (*ppr_r)->tree_p;
  585. X        *ppr_q = *ppr_r;
  586. X        *ppr_r = (*ppr_r)->tree_l;
  587. X        *pi_balance = TRUE;
  588. X    }
  589. X
  590. X    EXITV
  591. X}
  592. X
  593. X
  594. Xstatic void balanceL(ppr_p, pi_balance)
  595. Xtree    **ppr_p;
  596. Xint    *pi_balance;
  597. X{
  598. X    tree    *p1, *p2;
  599. X    int    b1, b2;
  600. X
  601. X    ENTER("balanceL")
  602. X    MSG("left branch has shrunk")
  603. X
  604. X    switch ((*ppr_p)->tree_b)
  605. X    {
  606. X    case -1: MSG("was imbalanced, fixed implicitly")
  607. X        (*ppr_p)->tree_b = 0;
  608. X        break;
  609. X    case 0:    MSG("was okay, is now one off")
  610. X        (*ppr_p)->tree_b = 1;
  611. X        *pi_balance = FALSE;
  612. X        break;
  613. X    case 1:    MSG("was already off, this is too much")
  614. X        p1 = (*ppr_p)->tree_r;
  615. X        b1 = p1->tree_b;
  616. X        if (b1 >= 0) {
  617. X            MSG("single RR")
  618. X            (*ppr_p)->tree_r = p1->tree_l;
  619. X            p1->tree_l = *ppr_p;
  620. X            if (b1 == 0) {
  621. X                MSG("b1 == 0")
  622. X                (*ppr_p)->tree_b = 1;
  623. X                p1->tree_b = -1;
  624. X                *pi_balance = FALSE;
  625. X            } else {
  626. X                MSG("b1 != 0")
  627. X                (*ppr_p)->tree_b = 0;
  628. X                p1->tree_b = 0;
  629. X            }
  630. X            *ppr_p = p1;
  631. X        } else {
  632. X            MSG("double RL")
  633. X            p2 = p1->tree_l;
  634. X            b2 = p2->tree_b;
  635. X            p1->tree_l = p2->tree_r;
  636. X            p2->tree_r = p1;
  637. X            (*ppr_p)->tree_r = p2->tree_l;
  638. X            p2->tree_l = *ppr_p;
  639. X            if (b2 == 1)
  640. X                (*ppr_p)->tree_b = -1;
  641. X            else
  642. X                (*ppr_p)->tree_b = 0;
  643. X            if (b2 == -1)
  644. X                p1->tree_b = 1;
  645. X            else
  646. X                p1->tree_b = 0;
  647. X            *ppr_p = p2;
  648. X            p2->tree_b = 0;
  649. X        }
  650. X    }
  651. X    EXITV
  652. X}
  653. X
  654. X
  655. Xstatic void balanceR(ppr_p, pi_balance)
  656. Xtree    **ppr_p;
  657. Xint    *pi_balance;
  658. X{
  659. X    tree    *p1, *p2;
  660. X    int    b1, b2;
  661. X
  662. X    ENTER("balanceR")
  663. X    MSG("right branch has shrunk")
  664. X    switch ((*ppr_p)->tree_b)
  665. X    {
  666. X    case 1:    MSG("was imbalanced, fixed implicitly")
  667. X        (*ppr_p)->tree_b = 0;
  668. X        break;
  669. X    case 0:    MSG("was okay, is now one off")
  670. X        (*ppr_p)->tree_b = -1;
  671. X        *pi_balance = FALSE;
  672. X        break;
  673. X    case -1: MSG("was already off, this is too much")
  674. X        p1 = (*ppr_p)->tree_l;
  675. X        b1 = p1->tree_b;
  676. X        if (b1 <= 0) {
  677. X            MSG("single LL")
  678. X            (*ppr_p)->tree_l = p1->tree_r;
  679. X            p1->tree_r = *ppr_p;
  680. X            if (b1 == 0) {
  681. X                MSG("b1 == 0")
  682. X                (*ppr_p)->tree_b = -1;
  683. X                p1->tree_b = 1;
  684. X                *pi_balance = FALSE;
  685. X            } else {
  686. X                MSG("b1 != 0")
  687. X                (*ppr_p)->tree_b = 0;
  688. X                p1->tree_b = 0;
  689. X            }
  690. X            *ppr_p = p1;
  691. X        } else {
  692. X            MSG("double LR")
  693. X            p2 = p1->tree_r;
  694. X            b2 = p2->tree_b;
  695. X            p1->tree_r = p2->tree_l;
  696. X            p2->tree_l = p1;
  697. X            (*ppr_p)->tree_l = p2->tree_r;
  698. X            p2->tree_r = *ppr_p;
  699. X            if (b2 == -1)
  700. X                (*ppr_p)->tree_b = 1;
  701. X            else
  702. X                (*ppr_p)->tree_b = 0;
  703. X            if (b2 == 1)
  704. X                p1->tree_b = -1;
  705. X            else
  706. X                p1->tree_b = 0;
  707. X            *ppr_p = p2;
  708. X            p2->tree_b = 0;
  709. X        }
  710. X    }
  711. X    EXITV
  712. X}
  713. X
  714. X
  715. Xint tree_trav(ppr_tree, pfi_uar)
  716. Xtree    **ppr_tree;
  717. Xint    (*pfi_uar)();
  718. X{
  719. X    ENTER("tree_trav")
  720. X
  721. X    if (!*ppr_tree)
  722. X        EXIT(TRUE)
  723. X
  724. X    if (!tree_trav(&(**ppr_tree).tree_l, pfi_uar))
  725. X        EXIT(FALSE)
  726. X    if (!(*pfi_uar)((**ppr_tree).tree_p))
  727. X        EXIT(FALSE)
  728. X    if (!tree_trav(&(**ppr_tree).tree_r, pfi_uar))
  729. X        EXIT(FALSE)
  730. X    EXIT(TRUE)
  731. X}
  732. X
  733. X
  734. Xvoid tree_mung(ppr_tree, pfi_uar)
  735. Xtree    **ppr_tree;
  736. Xint    (*pfi_uar)();
  737. X{
  738. X    ENTER("tree_mung")
  739. X    if (*ppr_tree)
  740. X    {
  741. X        tree_mung(&(**ppr_tree).tree_l, pfi_uar);
  742. X        tree_mung(&(**ppr_tree).tree_r, pfi_uar);
  743. X        if (pfi_uar)
  744. X            (*pfi_uar)((**ppr_tree).tree_p);
  745. X        free(*ppr_tree);
  746. X        *ppr_tree = NULL;
  747. X    }
  748. X    EXITV
  749. X}
  750. END_OF_tree.c
  751. if test 10313 -ne `wc -c <tree.c`; then
  752.     echo shar: \"tree.c\" unpacked with wrong size!
  753. fi
  754. # end of overwriting check
  755. fi
  756. if test -f tree.h -a "${1}" != "-c" ; then 
  757.   echo shar: Will not over-write existing file \"tree.h\"
  758. else
  759. echo shar: Extracting \"tree.h\" \(253 characters\)
  760. sed "s/^X//" >tree.h <<'END_OF_tree.h'
  761. X/* tree.h - declare structures used by tree.c
  762. X * vix 27jun86 [broken out of tree.c]
  763. X */
  764. X
  765. X
  766. X#ifndef    _TREE_FLAG
  767. X#define    _TREE_FLAG
  768. X
  769. X
  770. Xtypedef    struct    tree_s
  771. X    {
  772. X        struct    tree_s    *tree_l, *tree_r;
  773. X        short        tree_b;
  774. X        char        *tree_p;
  775. X    }
  776. X    tree;
  777. X
  778. X
  779. X#endif    _TREE_FLAG
  780. END_OF_tree.h
  781. if test 253 -ne `wc -c <tree.h`; then
  782.     echo shar: \"tree.h\" unpacked with wrong size!
  783. fi
  784. # end of overwriting check
  785. fi
  786. if test -f tree.man3 -a "${1}" != "-c" ; then 
  787.   echo shar: Will not over-write existing file \"tree.man3\"
  788. else
  789. echo shar: Extracting \"tree.man3\" \(3448 characters\)
  790. sed "s/^X//" >tree.man3 <<'END_OF_tree.man3'
  791. X.TH TREE 2 "23 June 1986"
  792. X.UC 4
  793. X.SH NAME
  794. Xtree_init, tree_mung, tree_srch, tree_add, tree_delete, tree_trav \- balanced binary tree routines
  795. X.SH SYNOPSIS
  796. X.nf
  797. X.B void
  798. X.B tree_init(tree)
  799. X.B int **tree;
  800. X.PP
  801. X.B int *
  802. X.B tree_srch(tree, compare, data)
  803. X.B int **tree, (*compare)(), *data;
  804. X.PP
  805. X.B void
  806. X.B tree_add(tree, compare, data, del_uar)
  807. X.B int **tree, (*compare)(), *data, (*del_uar)();
  808. X.PP
  809. X.B int
  810. X.B tree_delete(tree, compare, data, del_uar)
  811. X.B int **tree, (*compare)(), *data, (*del_uar)();
  812. X.PP
  813. X.B int
  814. X.B tree_trav(tree, trav_uar)
  815. X.B int **tree, (*trav_uar)();
  816. X.PP
  817. X.B void
  818. X.B tree_mung(tree, del_uar)
  819. X.B int **tree, (*del_uar)();
  820. X.fi
  821. X.SH DESCRIPTION
  822. XThese functions create and manipulate a balanced binary (AVL) tree.  Each node
  823. Xof the tree contains the expected left & right subtree pointers, a short-int
  824. Xbalance indicator, and a pointer to the user-data.  On a 32-bit system, this
  825. Xmeans an overhead of 4+4+2+4 bytes per node.  There is no key data type
  826. Xenforced by this package; a caller-supplied compare routine is used to compare
  827. Xuser-data blocks.
  828. X.PP
  829. X.I Tree_init
  830. Xcreates an empty tree and binds it to
  831. X.I tree
  832. X(which for this and all other routines in this package should be declared as
  833. Xa pointer to integer and passed by reference), which can then be used by other
  834. Xroutines in this package.  Note that more than one
  835. X.I tree
  836. Xvariable can exist at once; thus multiple trees can be manipulated
  837. Xsimultaneously.
  838. X.PP
  839. X.I Tree_srch
  840. Xsearches a tree for a specific node and returns either
  841. X.I NULL
  842. Xif no node was found, or the address of the user-data for that node if one was
  843. Xfound.
  844. X.I compare
  845. Xis the address of a function to compare two user-data blocks.  This routine
  846. Xshould work much the way 
  847. X.IR strcmp 2
  848. Xdoes; in fact,
  849. X.I strcmp
  850. Xcould be used if the user-data was a null-terminated string.
  851. X.I data
  852. Xis the address of a user-data block to be used via
  853. X.I compare
  854. Xas the search criteria.  The tree is searched for a node where
  855. X.I compare
  856. Xreturns 0.
  857. X.PP
  858. X.I Tree_add
  859. Xinserts or replaces a node in the specified tree.  The tree specified by
  860. X.I tree
  861. Xis searched as in
  862. X.I tree_srch,
  863. Xand if a node is found to match
  864. X.I data,
  865. Xthen the
  866. X.I del_uar
  867. Xfunction is called with the address of the user-data block for the node
  868. X(this routine should deallocate any dynamic memory which is pointed to
  869. Xexclusively by the node); the user-data pointer for the node is then
  870. Xreplaced by the value of
  871. X.I data.
  872. XIf no node is found to match, a new node is added (which may or may not
  873. Xcause a transparent rebalance operation), with a user-data pointer equal
  874. Xto
  875. X.I data.
  876. X.PP
  877. X.I Tree_delete
  878. Xdeletes a node from
  879. X.I tree.
  880. XA rebalance may or may not occur, depending on where the node is removed from
  881. Xand what the rest of the tree looks like.
  882. X.I Tree_delete
  883. Xreturns TRUE if a node was deleted, FALSE otherwise.
  884. X.PP
  885. X.I Tree_trav
  886. Xtraverses all of
  887. X.I tree,
  888. Xcalling
  889. X.I trav_uar
  890. Xwith the address of each user-data block.  If
  891. X.I trav_uar
  892. Xreturns FALSE at any time,
  893. X.I tree_trav
  894. Xwill immediately return FALSE to its caller.  Otherwise all nodes will be 
  895. Xreached and
  896. X.I tree_trav
  897. Xwill return TRUE.
  898. X.PP
  899. X.I Tree_mung
  900. Xdeletes every node in
  901. X.I tree,
  902. Xcalling
  903. X.I del_uar
  904. Xwith the user-data address from each node (see
  905. X.I tree_add
  906. Xand
  907. X.I tree_delete
  908. Xabove).  The tree is left in the same state that
  909. X.I tree_init
  910. Xleaves it in \- i.e., empty.
  911. X.SH AUTHOR
  912. XPaul Vixie, converted and augumented from Modula-2 examples in
  913. X.I Algorithms & Data Structures,
  914. XNiklaus Wirth, Prentice-Hall, ISBN 0-13-022005-1.
  915. END_OF_tree.man3
  916. if test 3448 -ne `wc -c <tree.man3`; then
  917.     echo shar: \"tree.man3\" unpacked with wrong size!
  918. fi
  919. # end of overwriting check
  920. fi
  921. if test -f vixie.h -a "${1}" != "-c" ; then 
  922.   echo shar: Will not over-write existing file \"vixie.h\"
  923. else
  924. echo shar: Extracting \"vixie.h\" \(1618 characters\)
  925. sed "s/^X//" >vixie.h <<'END_OF_vixie.h'
  926. X/* vixie.h - include file to define general vixie-type things
  927. X * v1.0 vix 21jun86 [broken out of as.h]
  928. X */
  929. X
  930. X#ifdef    DOCUMENTATION
  931. X
  932. XThere are two macros you can define before including this file which can
  933. Xchange the things defined by this file.
  934. X
  935. XDEBUG:    if defined, will cause enter/exit messages to be printed by the
  936. X    ENTER/EXIT/EXITV macros.  If not defined, causes ENTER to do nothing,
  937. X    and EXIT/EXITV to generate 'return' without any messages.
  938. X
  939. X    If defined, should be set to the name of the including module.
  940. X
  941. XMAIN:    Should be defined for a program containing a main() function which
  942. X    is linked with other modules which include this file.
  943. X
  944. X    Value is not important, only existence/nonexistence matters.
  945. X
  946. X#endif    DOCUMENTATION
  947. X
  948. X
  949. X#ifndef    _VIXIE_FLAG
  950. X#define    _VIXIE_FLAG
  951. X
  952. X
  953. X                        /*--- debugging stuff ---*/
  954. X#define    MAXPROC    256
  955. X
  956. X#ifdef DEBUG
  957. X#define    ENTER(proc) { \
  958. X            APC_PROCS[I_PROC] = proc; \
  959. X            printf("ENTER(%d:%s.%s)\n", \
  960. X                I_PROC, DEBUG, APC_PROCS[I_PROC]); \
  961. X            I_PROC++; \
  962. X        }
  963. X#define    EXIT(value) { \
  964. X            I_PROC--; \
  965. X            printf("EXIT(%d:%s.%s)\n", \
  966. X                I_PROC, DEBUG, \
  967. X                APC_PROCS[I_PROC]); \
  968. X            return value; \
  969. X        }
  970. X#define    EXITV { \
  971. X            I_PROC--; \
  972. X            printf("EXITV(%d:%s.%s)\n", \
  973. X                I_PROC, DEBUG, \
  974. X                APC_PROCS[I_PROC]); \
  975. X            return value; \
  976. X        }
  977. X#else
  978. X#define    ENTER(proc)
  979. X#define    EXIT(value)    {return value;}
  980. X#define    EXITV        return;
  981. X#endif
  982. X
  983. X#ifdef MAIN
  984. Xint    I_PROC = 0;
  985. Xchar    *APC_PROCS[MAXPROC];
  986. X#else
  987. Xextern    int    I_PROC;
  988. Xextern    char    *APC_PROCS[MAXPROC];
  989. X#endif
  990. X
  991. X
  992. X            /*--- why didn't k&r put these into stdio.h? ---*/
  993. X#define    TRUE        1
  994. X#define    FALSE        0
  995. Xextern    char        *malloc(), *calloc();
  996. X
  997. X
  998. X#endif    _VIXIE_FLAG
  999. END_OF_vixie.h
  1000. if test 1618 -ne `wc -c <vixie.h`; then
  1001.     echo shar: \"vixie.h\" unpacked with wrong size!
  1002. fi
  1003. # end of overwriting check
  1004. fi
  1005. echo shar: End of shell archive.
  1006. exit 0
  1007. -- 
  1008.  
  1009. Rich $alz
  1010. Cronus Project, BBN Labs            rsalz@bbn.com
  1011. Moderator, comp.sources.unix            sources@uunet.uu.net
  1012.