avl.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. #ifdef HAVE_CONFIG_H
  39. # include <config.h>
  40. #endif
  41. /* avl.c - routines to implement an avl tree */
  42. /*
  43. * Copyright (c) 1993 Regents of the University of Michigan.
  44. * All rights reserved.
  45. *
  46. * Redistribution and use in source and binary forms are permitted
  47. * provided that this notice is preserved and that due credit is given
  48. * to the University of Michigan at Ann Arbor. The name of the University
  49. * may not be used to endorse or promote products derived from this
  50. * software without specific prior written permission. This software
  51. * is provided ``as is'' without express or implied warranty.
  52. */
  53. #if 0
  54. static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University of Michigan.\nAll rights reserved.\n";
  55. static char avl_version[] = "AVL library version 1.0\n";
  56. #endif
  57. #ifdef _WIN32
  58. typedef char *caddr_t;
  59. #define WIN32_LEAN_AND_MEAN
  60. #include <windows.h>
  61. #endif
  62. #include <sys/types.h>
  63. #include <stdlib.h>
  64. #include <stdio.h>
  65. #include "avl.h"
  66. #define ROTATERIGHT(x) { \
  67. Avlnode *tmp;\
  68. if ( *x == NULL || (*x)->avl_left == NULL ) {\
  69. (void) printf("RR error\n"); exit(1); \
  70. }\
  71. tmp = (*x)->avl_left;\
  72. (*x)->avl_left = tmp->avl_right;\
  73. tmp->avl_right = *x;\
  74. *x = tmp;\
  75. }
  76. #define ROTATELEFT(x) { \
  77. Avlnode *tmp;\
  78. if ( *x == NULL || (*x)->avl_right == NULL ) {\
  79. (void) printf("RL error\n"); exit(1); \
  80. }\
  81. tmp = (*x)->avl_right;\
  82. (*x)->avl_right = tmp->avl_left;\
  83. tmp->avl_left = *x;\
  84. *x = tmp;\
  85. }
  86. /*
  87. * ravl_insert - called from avl_insert() to do a recursive insert into
  88. * and balance of an avl tree.
  89. */
  90. static int
  91. ravl_insert(
  92. Avlnode **iroot,
  93. caddr_t data,
  94. int *taller,
  95. IFP fcmp, /* comparison function */
  96. IFP fdup, /* function to call for duplicates */
  97. int depth
  98. )
  99. {
  100. int rc, cmp, tallersub;
  101. Avlnode *l, *r;
  102. if ( *iroot == 0 ) {
  103. if ( (*iroot = (Avlnode *) malloc( sizeof( Avlnode ) ))
  104. == NULL ) {
  105. return( -1 );
  106. }
  107. (*iroot)->avl_left = 0;
  108. (*iroot)->avl_right = 0;
  109. (*iroot)->avl_bf = 0;
  110. (*iroot)->avl_data = data;
  111. *taller = 1;
  112. return( 0 );
  113. }
  114. cmp = (*fcmp)( data, (*iroot)->avl_data );
  115. /* equal - duplicate name */
  116. if ( cmp == 0 ) {
  117. *taller = 0;
  118. return( (*fdup)( (*iroot)->avl_data, data ) );
  119. }
  120. /* go right */
  121. else if ( cmp > 0 ) {
  122. rc = ravl_insert( &((*iroot)->avl_right), data, &tallersub,
  123. fcmp, fdup, depth );
  124. if ( tallersub )
  125. switch ( (*iroot)->avl_bf ) {
  126. case LH : /* left high - balance is restored */
  127. (*iroot)->avl_bf = EH;
  128. *taller = 0;
  129. break;
  130. case EH : /* equal height - now right heavy */
  131. (*iroot)->avl_bf = RH;
  132. *taller = 1;
  133. break;
  134. case RH : /* right heavy to start - right balance */
  135. r = (*iroot)->avl_right;
  136. switch ( r->avl_bf ) {
  137. case LH : /* double rotation left */
  138. l = r->avl_left;
  139. switch ( l->avl_bf ) {
  140. case LH : (*iroot)->avl_bf = EH;
  141. r->avl_bf = RH;
  142. break;
  143. case EH : (*iroot)->avl_bf = EH;
  144. r->avl_bf = EH;
  145. break;
  146. case RH : (*iroot)->avl_bf = LH;
  147. r->avl_bf = EH;
  148. break;
  149. }
  150. l->avl_bf = EH;
  151. ROTATERIGHT( (&r) )
  152. (*iroot)->avl_right = r;
  153. ROTATELEFT( iroot )
  154. *taller = 0;
  155. break;
  156. case EH : /* This should never happen */
  157. break;
  158. case RH : /* single rotation left */
  159. (*iroot)->avl_bf = EH;
  160. r->avl_bf = EH;
  161. ROTATELEFT( iroot )
  162. *taller = 0;
  163. break;
  164. }
  165. break;
  166. }
  167. else
  168. *taller = 0;
  169. }
  170. /* go left */
  171. else {
  172. rc = ravl_insert( &((*iroot)->avl_left), data, &tallersub,
  173. fcmp, fdup, depth );
  174. if ( tallersub )
  175. switch ( (*iroot)->avl_bf ) {
  176. case LH : /* left high to start - left balance */
  177. l = (*iroot)->avl_left;
  178. switch ( l->avl_bf ) {
  179. case LH : /* single rotation right */
  180. (*iroot)->avl_bf = EH;
  181. l->avl_bf = EH;
  182. ROTATERIGHT( iroot )
  183. *taller = 0;
  184. break;
  185. case EH : /* this should never happen */
  186. break;
  187. case RH : /* double rotation right */
  188. r = l->avl_right;
  189. switch ( r->avl_bf ) {
  190. case LH : (*iroot)->avl_bf = RH;
  191. l->avl_bf = EH;
  192. break;
  193. case EH : (*iroot)->avl_bf = EH;
  194. l->avl_bf = EH;
  195. break;
  196. case RH : (*iroot)->avl_bf = EH;
  197. l->avl_bf = LH;
  198. break;
  199. }
  200. r->avl_bf = EH;
  201. ROTATELEFT( (&l) )
  202. (*iroot)->avl_left = l;
  203. ROTATERIGHT( iroot )
  204. *taller = 0;
  205. break;
  206. }
  207. break;
  208. case EH : /* equal height - now left heavy */
  209. (*iroot)->avl_bf = LH;
  210. *taller = 1;
  211. break;
  212. case RH : /* right high - balance is restored */
  213. (*iroot)->avl_bf = EH;
  214. *taller = 0;
  215. break;
  216. }
  217. else
  218. *taller = 0;
  219. }
  220. return( rc );
  221. }
  222. /*
  223. * avl_insert -- insert a node containing data data into the avl tree
  224. * with root root. fcmp is a function to call to compare the data portion
  225. * of two nodes. it should take two arguments and return <, >, or == 0,
  226. * depending on whether its first argument is <, >, or == its second
  227. * argument (like strcmp, e.g.). fdup is a function to call when a duplicate
  228. * node is inserted. it should return 0, or -1 and its return value
  229. * will be the return value from avl_insert in the case of a duplicate node.
  230. * the function will be called with the original node's data as its first
  231. * argument and with the incoming duplicate node's data as its second
  232. * argument. this could be used, for example, to keep a count with each
  233. * node.
  234. *
  235. * NOTE: this routine may malloc memory
  236. */
  237. int
  238. avl_insert(
  239. Avlnode **root,
  240. caddr_t data,
  241. IFP fcmp,
  242. IFP fdup
  243. )
  244. {
  245. int taller;
  246. return( ravl_insert( root, data, &taller, fcmp, fdup, 0 ) );
  247. }
  248. /*
  249. * right_balance() - called from delete when root's right subtree has
  250. * been shortened because of a deletion.
  251. */
  252. static int
  253. right_balance( Avlnode **root )
  254. {
  255. int shorter= 0;
  256. Avlnode *r, *l;
  257. switch( (*root)->avl_bf ) {
  258. case RH: /* was right high - equal now */
  259. (*root)->avl_bf = EH;
  260. shorter = 1;
  261. break;
  262. case EH: /* was equal - left high now */
  263. (*root)->avl_bf = LH;
  264. shorter = 0;
  265. break;
  266. case LH: /* was right high - balance */
  267. l = (*root)->avl_left;
  268. switch ( l->avl_bf ) {
  269. case RH : /* double rotation left */
  270. r = l->avl_right;
  271. switch ( r->avl_bf ) {
  272. case RH :
  273. (*root)->avl_bf = EH;
  274. l->avl_bf = LH;
  275. break;
  276. case EH :
  277. (*root)->avl_bf = EH;
  278. l->avl_bf = EH;
  279. break;
  280. case LH :
  281. (*root)->avl_bf = RH;
  282. l->avl_bf = EH;
  283. break;
  284. }
  285. r->avl_bf = EH;
  286. ROTATELEFT( (&l) )
  287. (*root)->avl_left = l;
  288. ROTATERIGHT( root )
  289. shorter = 1;
  290. break;
  291. case EH : /* right rotation */
  292. (*root)->avl_bf = LH;
  293. l->avl_bf = RH;
  294. ROTATERIGHT( root );
  295. shorter = 0;
  296. break;
  297. case LH : /* single rotation right */
  298. (*root)->avl_bf = EH;
  299. l->avl_bf = EH;
  300. ROTATERIGHT( root )
  301. shorter = 1;
  302. break;
  303. }
  304. break;
  305. }
  306. return( shorter );
  307. }
  308. /*
  309. * left_balance() - called from delete when root's left subtree has
  310. * been shortened because of a deletion.
  311. */
  312. static int
  313. left_balance( Avlnode **root )
  314. {
  315. int shorter= 0;
  316. Avlnode *r, *l;
  317. switch( (*root)->avl_bf ) {
  318. case LH: /* was left high - equal now */
  319. (*root)->avl_bf = EH;
  320. shorter = 1;
  321. break;
  322. case EH: /* was equal - right high now */
  323. (*root)->avl_bf = RH;
  324. shorter = 0;
  325. break;
  326. case RH: /* was right high - balance */
  327. r = (*root)->avl_right;
  328. switch ( r->avl_bf ) {
  329. case LH : /* double rotation left */
  330. l = r->avl_left;
  331. switch ( l->avl_bf ) {
  332. case LH :
  333. (*root)->avl_bf = EH;
  334. r->avl_bf = RH;
  335. break;
  336. case EH :
  337. (*root)->avl_bf = EH;
  338. r->avl_bf = EH;
  339. break;
  340. case RH :
  341. (*root)->avl_bf = LH;
  342. r->avl_bf = EH;
  343. break;
  344. }
  345. l->avl_bf = EH;
  346. ROTATERIGHT( (&r) )
  347. (*root)->avl_right = r;
  348. ROTATELEFT( root )
  349. shorter = 1;
  350. break;
  351. case EH : /* single rotation left */
  352. (*root)->avl_bf = RH;
  353. r->avl_bf = LH;
  354. ROTATELEFT( root );
  355. shorter = 0;
  356. break;
  357. case RH : /* single rotation left */
  358. (*root)->avl_bf = EH;
  359. r->avl_bf = EH;
  360. ROTATELEFT( root )
  361. shorter = 1;
  362. break;
  363. }
  364. break;
  365. }
  366. return( shorter );
  367. }
  368. /*
  369. * ravl_delete() - called from avl_delete to do recursive deletion of a
  370. * node from an avl tree. It finds the node recursively, deletes it,
  371. * and returns shorter if the tree is shorter after the deletion and
  372. * rebalancing.
  373. */
  374. static caddr_t
  375. ravl_delete(
  376. Avlnode **root,
  377. caddr_t data,
  378. IFP fcmp,
  379. int *shorter
  380. )
  381. {
  382. int shortersubtree = 0;
  383. int cmp;
  384. caddr_t savedata;
  385. Avlnode *minnode, *savenode;
  386. if ( *root == NULLAVL )
  387. return( 0 );
  388. cmp = (*fcmp)( data, (*root)->avl_data );
  389. /* found it! */
  390. if ( cmp == 0 ) {
  391. savenode = *root;
  392. savedata = savenode->avl_data;
  393. /* simple cases: no left child */
  394. if ( (*root)->avl_left == 0 ) {
  395. *root = (*root)->avl_right;
  396. *shorter = 1;
  397. free( (char *) savenode );
  398. return( savedata );
  399. /* no right child */
  400. } else if ( (*root)->avl_right == 0 ) {
  401. *root = (*root)->avl_left;
  402. *shorter = 1;
  403. free( (char *) savenode );
  404. return( savedata );
  405. }
  406. /*
  407. * avl_getmin will return to us the smallest node greater
  408. * than the one we are trying to delete. deleting this node
  409. * from the right subtree is guaranteed to end in one of the
  410. * simple cases above.
  411. */
  412. minnode = (*root)->avl_right;
  413. while ( minnode->avl_left != NULLAVL )
  414. minnode = minnode->avl_left;
  415. /* swap the data */
  416. (*root)->avl_data = minnode->avl_data;
  417. minnode->avl_data = savedata;
  418. savedata = ravl_delete( &(*root)->avl_right, data, fcmp,
  419. &shortersubtree );
  420. if ( shortersubtree )
  421. *shorter = right_balance( root );
  422. else
  423. *shorter = 0;
  424. /* go left */
  425. } else if ( cmp < 0 ) {
  426. if ( (savedata = ravl_delete( &(*root)->avl_left, data, fcmp,
  427. &shortersubtree )) == 0 ) {
  428. *shorter = 0;
  429. return( 0 );
  430. }
  431. /* left subtree shorter? */
  432. if ( shortersubtree )
  433. *shorter = left_balance( root );
  434. else
  435. *shorter = 0;
  436. /* go right */
  437. } else {
  438. if ( (savedata = ravl_delete( &(*root)->avl_right, data, fcmp,
  439. &shortersubtree )) == 0 ) {
  440. *shorter = 0;
  441. return( 0 );
  442. }
  443. if ( shortersubtree )
  444. *shorter = right_balance( root );
  445. else
  446. *shorter = 0;
  447. }
  448. return( savedata );
  449. }
  450. /*
  451. * avl_delete() - deletes the node containing data (according to fcmp) from
  452. * the avl tree rooted at root.
  453. */
  454. caddr_t
  455. avl_delete( Avlnode **root, caddr_t data, IFP fcmp )
  456. {
  457. int shorter;
  458. return( ravl_delete( root, data, fcmp, &shorter ) );
  459. }
  460. static int
  461. avl_inapply( Avlnode *root, IFP fn, caddr_t arg, int stopflag )
  462. {
  463. if ( root == 0 )
  464. return( AVL_NOMORE );
  465. if ( root->avl_left != 0 )
  466. if ( avl_inapply( root->avl_left, fn, arg, stopflag )
  467. == stopflag )
  468. return( stopflag );
  469. if ( (*fn)( root->avl_data, arg ) == stopflag )
  470. return( stopflag );
  471. if ( root->avl_right == 0 )
  472. return( AVL_NOMORE );
  473. else
  474. return( avl_inapply( root->avl_right, fn, arg, stopflag ) );
  475. }
  476. static int
  477. avl_postapply( Avlnode *root, IFP fn, caddr_t arg, int stopflag )
  478. {
  479. if ( root == 0 )
  480. return( AVL_NOMORE );
  481. if ( root->avl_left != 0 )
  482. if ( avl_postapply( root->avl_left, fn, arg, stopflag )
  483. == stopflag )
  484. return( stopflag );
  485. if ( root->avl_right != 0 )
  486. if ( avl_postapply( root->avl_right, fn, arg, stopflag )
  487. == stopflag )
  488. return( stopflag );
  489. return( (*fn)( root->avl_data, arg ) );
  490. }
  491. static int
  492. avl_preapply( Avlnode *root, IFP fn, caddr_t arg, int stopflag )
  493. {
  494. if ( root == 0 )
  495. return( AVL_NOMORE );
  496. if ( (*fn)( root->avl_data, arg ) == stopflag )
  497. return( stopflag );
  498. if ( root->avl_left != 0 )
  499. if ( avl_preapply( root->avl_left, fn, arg, stopflag )
  500. == stopflag )
  501. return( stopflag );
  502. if ( root->avl_right == 0 )
  503. return( AVL_NOMORE );
  504. else
  505. return( avl_preapply( root->avl_right, fn, arg, stopflag ) );
  506. }
  507. /*
  508. * avl_apply -- avl tree root is traversed, function fn is called with
  509. * arguments arg and the data portion of each node. if fn returns stopflag,
  510. * the traversal is cut short, otherwise it continues. Do not use -6 as
  511. * a stopflag, as this is what is used to indicate the traversal ran out
  512. * of nodes.
  513. */
  514. int
  515. avl_apply(
  516. Avlnode *root,
  517. IFP fn,
  518. caddr_t arg,
  519. int stopflag,
  520. int type
  521. )
  522. {
  523. switch ( type ) {
  524. case AVL_INORDER:
  525. return( avl_inapply( root, fn, arg, stopflag ) );
  526. case AVL_PREORDER:
  527. return( avl_preapply( root, fn, arg, stopflag ) );
  528. case AVL_POSTORDER:
  529. return( avl_postapply( root, fn, arg, stopflag ) );
  530. default:
  531. fprintf( stderr, "Invalid traversal type %d\n", type );
  532. return( -1 );
  533. }
  534. /* NOTREACHED */
  535. }
  536. /*
  537. * avl_prefixapply - traverse avl tree root, applying function fprefix
  538. * to any nodes that match. fcmp is called with data as its first arg
  539. * and the current node's data as its second arg. it should return
  540. * 0 if they match, < 0 if data is less, and > 0 if data is greater.
  541. * the idea is to efficiently find all nodes that are prefixes of
  542. * some key... Like avl_apply, this routine also takes a stopflag
  543. * and will return prematurely if fmatch returns this value. Otherwise,
  544. * AVL_NOMORE is returned.
  545. */
  546. int
  547. avl_prefixapply(
  548. Avlnode *root,
  549. caddr_t data,
  550. IFP fmatch,
  551. caddr_t marg,
  552. IFP fcmp,
  553. caddr_t carg,
  554. int stopflag
  555. )
  556. {
  557. int cmp;
  558. if ( root == 0 )
  559. return( AVL_NOMORE );
  560. cmp = (*fcmp)( data, root->avl_data, carg );
  561. if ( cmp == 0 ) {
  562. if ( (*fmatch)( root->avl_data, marg ) == stopflag )
  563. return( stopflag );
  564. if ( root->avl_left != 0 )
  565. if ( avl_prefixapply( root->avl_left, data, fmatch,
  566. marg, fcmp, carg, stopflag ) == stopflag )
  567. return( stopflag );
  568. if ( root->avl_right != 0 )
  569. return( avl_prefixapply( root->avl_right, data, fmatch,
  570. marg, fcmp, carg, stopflag ) );
  571. else
  572. return( AVL_NOMORE );
  573. } else if ( cmp < 0 ) {
  574. if ( root->avl_left != 0 )
  575. return( avl_prefixapply( root->avl_left, data, fmatch,
  576. marg, fcmp, carg, stopflag ) );
  577. } else {
  578. if ( root->avl_right != 0 )
  579. return( avl_prefixapply( root->avl_right, data, fmatch,
  580. marg, fcmp, carg, stopflag ) );
  581. }
  582. return( AVL_NOMORE );
  583. }
  584. /*
  585. * avl_free -- traverse avltree root, freeing the memory it is using.
  586. * the dfree() is called to free the data portion of each node. The
  587. * number of items actually freed is returned.
  588. */
  589. int
  590. avl_free( Avlnode *root, IFP dfree )
  591. {
  592. int nleft, nright;
  593. if ( root == 0 )
  594. return( 0 );
  595. nleft = nright = 0;
  596. if ( root->avl_left != 0 )
  597. nleft = avl_free( root->avl_left, dfree );
  598. if ( root->avl_right != 0 )
  599. nright = avl_free( root->avl_right, dfree );
  600. if ( dfree )
  601. (*dfree)( root->avl_data );
  602. free( (char *)root );
  603. return( nleft + nright + 1 );
  604. }
  605. /*
  606. * avl_find -- search avltree root for a node with data data. the function
  607. * cmp is used to compare things. it is called with data as its first arg
  608. * and the current node data as its second. it should return 0 if they match,
  609. * < 0 if arg1 is less than arg2 and > 0 if arg1 is greater than arg2.
  610. */
  611. caddr_t
  612. avl_find( Avlnode *root, caddr_t data, IFP fcmp )
  613. {
  614. int cmp;
  615. while ( root != 0 && (cmp = (*fcmp)( data, root->avl_data )) != 0 ) {
  616. if ( cmp < 0 )
  617. root = root->avl_left;
  618. else
  619. root = root->avl_right;
  620. }
  621. return( root ? root->avl_data : 0 );
  622. }
  623. /*
  624. * avl_find_lin -- search avltree root linearly for a node with data data.
  625. * the function cmp is used to compare things. it is called with data as its
  626. * first arg and the current node data as its second. it should return 0 if
  627. * they match, non-zero otherwise.
  628. */
  629. caddr_t
  630. avl_find_lin( Avlnode *root, caddr_t data, IFP fcmp )
  631. {
  632. caddr_t res;
  633. if ( root == 0 )
  634. return( NULL );
  635. if ( (*fcmp)( data, root->avl_data ) == 0 )
  636. return( root->avl_data );
  637. if ( root->avl_left != 0 )
  638. if ( (res = avl_find_lin( root->avl_left, data, fcmp ))
  639. != NULL )
  640. return( res );
  641. if ( root->avl_right == 0 )
  642. return( NULL );
  643. else
  644. return( avl_find_lin( root->avl_right, data, fcmp ) );
  645. }
  646. static caddr_t *avl_list = (caddr_t *)0;
  647. static int avl_maxlist = 0;
  648. static int avl_nextlist = 0;
  649. #define AVL_GRABSIZE 100
  650. /* ARGSUSED */
  651. static int
  652. avl_buildlist( caddr_t data, int arg )
  653. {
  654. static int slots = 0;
  655. if ( avl_list == (caddr_t *) 0 ) {
  656. avl_list = (caddr_t *) malloc(AVL_GRABSIZE * sizeof(caddr_t));
  657. slots = AVL_GRABSIZE;
  658. avl_maxlist = 0;
  659. } else if ( avl_maxlist == slots ) {
  660. slots += AVL_GRABSIZE;
  661. avl_list = (caddr_t *) realloc( (char *) avl_list,
  662. (unsigned) slots * sizeof(caddr_t));
  663. }
  664. avl_list[ avl_maxlist++ ] = data;
  665. return( 0 );
  666. }
  667. /*
  668. * avl_getfirst() and avl_getnext() are provided as alternate tree
  669. * traversal methods, to be used when a single function cannot be
  670. * provided to be called with every node in the tree. avl_getfirst()
  671. * traverses the tree and builds a linear list of all the nodes,
  672. * returning the first node. avl_getnext() returns the next thing
  673. * on the list built by avl_getfirst(). This means that avl_getfirst()
  674. * can take a while, and that the tree should not be messed with while
  675. * being traversed in this way, and that multiple traversals (even of
  676. * different trees) cannot be active at once.
  677. */
  678. caddr_t
  679. avl_getfirst( Avlnode *root )
  680. {
  681. if ( avl_list ) {
  682. free( (char *) avl_list);
  683. avl_list = (caddr_t *) 0;
  684. }
  685. avl_maxlist = 0;
  686. avl_nextlist = 0;
  687. if ( root == 0 )
  688. return( 0 );
  689. (void) avl_apply( root, avl_buildlist, (caddr_t) 0, -1, AVL_INORDER );
  690. if(avl_list && avl_list[avl_nextlist++]){
  691. return avl_list[avl_nextlist];
  692. } else {
  693. return( NULL );
  694. }
  695. }
  696. caddr_t
  697. avl_getnext()
  698. {
  699. if ( avl_list == 0 )
  700. return( 0 );
  701. if ( avl_nextlist == avl_maxlist ) {
  702. free( (caddr_t) avl_list);
  703. avl_list = (caddr_t *) 0;
  704. return( 0 );
  705. }
  706. return( avl_list[ avl_nextlist++ ] );
  707. }
  708. int avl_dup_error()
  709. {
  710. return( -1 );
  711. }
  712. int avl_dup_ok()
  713. {
  714. return( 0 );
  715. }