avl.c 19 KB

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