avl.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. /* avl.c - routines to implement an avl tree */
  2. /* $OpenLDAP$ */
  3. /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  4. *
  5. * Copyright 1998-2022 The OpenLDAP Foundation.
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted only as authorized by the OpenLDAP
  10. * Public License.
  11. *
  12. * A copy of this license is available in the file LICENSE in the
  13. * top-level directory of the distribution or, alternatively, at
  14. * <http://www.OpenLDAP.org/license.html>.
  15. */
  16. /* Portions Copyright (c) 1993 Regents of the University of Michigan.
  17. * All rights reserved.
  18. *
  19. * Redistribution and use in source and binary forms are permitted
  20. * provided that this notice is preserved and that due credit is given
  21. * to the University of Michigan at Ann Arbor. The name of the University
  22. * may not be used to endorse or promote products derived from this
  23. * software without specific prior written permission. This software
  24. * is provided ``as is'' without express or implied warranty.
  25. */
  26. /* ACKNOWLEDGEMENTS:
  27. * This work was originally developed by the University of Michigan
  28. * (as part of U-MICH LDAP). Additional significant contributors
  29. * include:
  30. * Howard Y. Chu
  31. * Hallvard B. Furuseth
  32. * Kurt D. Zeilenga
  33. */
  34. #include "portable.h"
  35. #include <limits.h>
  36. #include <stdio.h>
  37. #include <ac/stdlib.h>
  38. #ifdef CSRIMALLOC
  39. #define ber_memalloc malloc
  40. #define ber_memrealloc realloc
  41. #define ber_memfree free
  42. #else
  43. #include "lber.h"
  44. #endif
  45. #define AVL_INTERNAL
  46. #include "ldap_avl.h"
  47. /* Maximum tree depth this host's address space could support */
  48. #define MAX_TREE_DEPTH (sizeof(void *) * CHAR_BIT)
  49. static const int avl_bfs[] = {LH, RH};
  50. /*
  51. * ldap_avl_insert -- insert a node containing data data into the avl tree
  52. * with root root. fcmp is a function to call to compare the data portion
  53. * of two nodes. it should take two arguments and return <, >, or == 0,
  54. * depending on whether its first argument is <, >, or == its second
  55. * argument (like strcmp, e.g.). fdup is a function to call when a duplicate
  56. * node is inserted. it should return 0, or -1 and its return value
  57. * will be the return value from ldap_avl_insert in the case of a duplicate node.
  58. * the function will be called with the original node's data as its first
  59. * argument and with the incoming duplicate node's data as its second
  60. * argument. this could be used, for example, to keep a count with each
  61. * node.
  62. *
  63. * NOTE: this routine may malloc memory
  64. */
  65. int
  66. ldap_avl_insert( Avlnode ** root, void *data, AVL_CMP fcmp, AVL_DUP fdup )
  67. {
  68. Avlnode *t, *p, *s, *q, *r;
  69. int a, cmp, ncmp;
  70. if ( *root == NULL ) {
  71. if (( r = (Avlnode *) ber_memalloc( sizeof( Avlnode ))) == NULL ) {
  72. return( -1 );
  73. }
  74. r->avl_link[0] = r->avl_link[1] = NULL;
  75. r->avl_data = data;
  76. r->avl_bits[0] = r->avl_bits[1] = AVL_CHILD;
  77. r->avl_bf = EH;
  78. *root = r;
  79. return( 0 );
  80. }
  81. t = NULL;
  82. s = p = *root;
  83. /* find insertion point */
  84. while (1) {
  85. cmp = fcmp( data, p->avl_data );
  86. if ( cmp == 0 )
  87. return (*fdup)( p->avl_data, data );
  88. cmp = (cmp > 0);
  89. q = p->avl_link[cmp];
  90. if (q == NULL) {
  91. /* insert */
  92. if (( q = (Avlnode *) ber_memalloc( sizeof( Avlnode ))) == NULL ) {
  93. return( -1 );
  94. }
  95. q->avl_link[0] = q->avl_link[1] = NULL;
  96. q->avl_data = data;
  97. q->avl_bits[0] = q->avl_bits[1] = AVL_CHILD;
  98. q->avl_bf = EH;
  99. p->avl_link[cmp] = q;
  100. break;
  101. } else if ( q->avl_bf ) {
  102. t = p;
  103. s = q;
  104. }
  105. p = q;
  106. }
  107. /* adjust balance factors */
  108. cmp = fcmp( data, s->avl_data ) > 0;
  109. r = p = s->avl_link[cmp];
  110. a = avl_bfs[cmp];
  111. while ( p != q ) {
  112. cmp = fcmp( data, p->avl_data ) > 0;
  113. p->avl_bf = avl_bfs[cmp];
  114. p = p->avl_link[cmp];
  115. }
  116. /* checks and balances */
  117. if ( s->avl_bf == EH ) {
  118. s->avl_bf = a;
  119. return 0;
  120. } else if ( s->avl_bf == -a ) {
  121. s->avl_bf = EH;
  122. return 0;
  123. } else if ( s->avl_bf == a ) {
  124. cmp = (a > 0);
  125. ncmp = !cmp;
  126. if ( r->avl_bf == a ) {
  127. /* single rotation */
  128. p = r;
  129. s->avl_link[cmp] = r->avl_link[ncmp];
  130. r->avl_link[ncmp] = s;
  131. s->avl_bf = 0;
  132. r->avl_bf = 0;
  133. } else if ( r->avl_bf == -a ) {
  134. /* double rotation */
  135. p = r->avl_link[ncmp];
  136. r->avl_link[ncmp] = p->avl_link[cmp];
  137. p->avl_link[cmp] = r;
  138. s->avl_link[cmp] = p->avl_link[ncmp];
  139. p->avl_link[ncmp] = s;
  140. if ( p->avl_bf == a ) {
  141. s->avl_bf = -a;
  142. r->avl_bf = 0;
  143. } else if ( p->avl_bf == -a ) {
  144. s->avl_bf = 0;
  145. r->avl_bf = a;
  146. } else {
  147. s->avl_bf = 0;
  148. r->avl_bf = 0;
  149. }
  150. p->avl_bf = 0;
  151. }
  152. /* Update parent */
  153. if ( t == NULL )
  154. *root = p;
  155. else if ( s == t->avl_right )
  156. t->avl_right = p;
  157. else
  158. t->avl_left = p;
  159. }
  160. return 0;
  161. }
  162. void*
  163. ldap_avl_delete( Avlnode **root, void* data, AVL_CMP fcmp )
  164. {
  165. Avlnode *p, *q, *r, *top;
  166. int side, side_bf, shorter, nside;
  167. /* parent stack */
  168. Avlnode *pptr[MAX_TREE_DEPTH];
  169. unsigned char pdir[MAX_TREE_DEPTH];
  170. int depth = 0;
  171. if ( *root == NULL )
  172. return NULL;
  173. p = *root;
  174. while (1) {
  175. side = fcmp( data, p->avl_data );
  176. if ( !side )
  177. break;
  178. side = ( side > 0 );
  179. pdir[depth] = side;
  180. pptr[depth++] = p;
  181. p = p->avl_link[side];
  182. if ( p == NULL )
  183. return p;
  184. }
  185. data = p->avl_data;
  186. /* If this node has two children, swap so we are deleting a node with
  187. * at most one child.
  188. */
  189. if ( p->avl_link[0] && p->avl_link[1] ) {
  190. /* find the immediate predecessor <q> */
  191. q = p->avl_link[0];
  192. side = depth;
  193. pdir[depth++] = 0;
  194. while (q->avl_link[1]) {
  195. pdir[depth] = 1;
  196. pptr[depth++] = q;
  197. q = q->avl_link[1];
  198. }
  199. /* swap links */
  200. r = p->avl_link[0];
  201. p->avl_link[0] = q->avl_link[0];
  202. q->avl_link[0] = r;
  203. q->avl_link[1] = p->avl_link[1];
  204. p->avl_link[1] = NULL;
  205. q->avl_bf = p->avl_bf;
  206. /* fix stack positions: old parent of p points to q */
  207. pptr[side] = q;
  208. if ( side ) {
  209. r = pptr[side-1];
  210. r->avl_link[pdir[side-1]] = q;
  211. } else {
  212. *root = q;
  213. }
  214. /* new parent of p points to p */
  215. if ( depth-side > 1 ) {
  216. r = pptr[depth-1];
  217. r->avl_link[1] = p;
  218. } else {
  219. q->avl_link[0] = p;
  220. }
  221. }
  222. /* now <p> has at most one child, get it */
  223. q = p->avl_link[0] ? p->avl_link[0] : p->avl_link[1];
  224. ber_memfree( p );
  225. if ( !depth ) {
  226. *root = q;
  227. return data;
  228. }
  229. /* set the child into p's parent */
  230. depth--;
  231. p = pptr[depth];
  232. side = pdir[depth];
  233. p->avl_link[side] = q;
  234. top = NULL;
  235. shorter = 1;
  236. while ( shorter ) {
  237. p = pptr[depth];
  238. side = pdir[depth];
  239. nside = !side;
  240. side_bf = avl_bfs[side];
  241. /* case 1: height unchanged */
  242. if ( p->avl_bf == EH ) {
  243. /* Tree is now heavier on opposite side */
  244. p->avl_bf = avl_bfs[nside];
  245. shorter = 0;
  246. } else if ( p->avl_bf == side_bf ) {
  247. /* case 2: taller subtree shortened, height reduced */
  248. p->avl_bf = EH;
  249. } else {
  250. /* case 3: shorter subtree shortened */
  251. if ( depth )
  252. top = pptr[depth-1]; /* p->parent; */
  253. else
  254. top = NULL;
  255. /* set <q> to the taller of the two subtrees of <p> */
  256. q = p->avl_link[nside];
  257. if ( q->avl_bf == EH ) {
  258. /* case 3a: height unchanged, single rotate */
  259. p->avl_link[nside] = q->avl_link[side];
  260. q->avl_link[side] = p;
  261. shorter = 0;
  262. q->avl_bf = side_bf;
  263. p->avl_bf = (- side_bf);
  264. } else if ( q->avl_bf == p->avl_bf ) {
  265. /* case 3b: height reduced, single rotate */
  266. p->avl_link[nside] = q->avl_link[side];
  267. q->avl_link[side] = p;
  268. shorter = 1;
  269. q->avl_bf = EH;
  270. p->avl_bf = EH;
  271. } else {
  272. /* case 3c: height reduced, balance factors opposite */
  273. r = q->avl_link[side];
  274. q->avl_link[side] = r->avl_link[nside];
  275. r->avl_link[nside] = q;
  276. p->avl_link[nside] = r->avl_link[side];
  277. r->avl_link[side] = p;
  278. if ( r->avl_bf == side_bf ) {
  279. q->avl_bf = (- side_bf);
  280. p->avl_bf = EH;
  281. } else if ( r->avl_bf == (- side_bf)) {
  282. q->avl_bf = EH;
  283. p->avl_bf = side_bf;
  284. } else {
  285. q->avl_bf = EH;
  286. p->avl_bf = EH;
  287. }
  288. r->avl_bf = EH;
  289. q = r;
  290. }
  291. /* a rotation has caused <q> (or <r> in case 3c) to become
  292. * the root. let <p>'s former parent know this.
  293. */
  294. if ( top == NULL ) {
  295. *root = q;
  296. } else if (top->avl_link[0] == p) {
  297. top->avl_link[0] = q;
  298. } else {
  299. top->avl_link[1] = q;
  300. }
  301. /* end case 3 */
  302. p = q;
  303. }
  304. if ( !depth )
  305. break;
  306. depth--;
  307. } /* end while(shorter) */
  308. return data;
  309. }
  310. static int
  311. avl_inapply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag )
  312. {
  313. if ( root == 0 )
  314. return( AVL_NOMORE );
  315. if ( root->avl_left != 0 )
  316. if ( avl_inapply( root->avl_left, fn, arg, stopflag )
  317. == stopflag )
  318. return( stopflag );
  319. if ( (*fn)( root->avl_data, arg ) == stopflag )
  320. return( stopflag );
  321. if ( root->avl_right == 0 )
  322. return( AVL_NOMORE );
  323. else
  324. return( avl_inapply( root->avl_right, fn, arg, stopflag ) );
  325. }
  326. static int
  327. avl_postapply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag )
  328. {
  329. if ( root == 0 )
  330. return( AVL_NOMORE );
  331. if ( root->avl_left != 0 )
  332. if ( avl_postapply( root->avl_left, fn, arg, stopflag )
  333. == stopflag )
  334. return( stopflag );
  335. if ( root->avl_right != 0 )
  336. if ( avl_postapply( root->avl_right, fn, arg, stopflag )
  337. == stopflag )
  338. return( stopflag );
  339. return( (*fn)( root->avl_data, arg ) );
  340. }
  341. static int
  342. avl_preapply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag )
  343. {
  344. if ( root == 0 )
  345. return( AVL_NOMORE );
  346. if ( (*fn)( root->avl_data, arg ) == stopflag )
  347. return( stopflag );
  348. if ( root->avl_left != 0 )
  349. if ( avl_preapply( root->avl_left, fn, arg, stopflag )
  350. == stopflag )
  351. return( stopflag );
  352. if ( root->avl_right == 0 )
  353. return( AVL_NOMORE );
  354. else
  355. return( avl_preapply( root->avl_right, fn, arg, stopflag ) );
  356. }
  357. /*
  358. * ldap_avl_apply -- avl tree root is traversed, function fn is called with
  359. * arguments arg and the data portion of each node. if fn returns stopflag,
  360. * the traversal is cut short, otherwise it continues. Do not use -6 as
  361. * a stopflag, as this is what is used to indicate the traversal ran out
  362. * of nodes.
  363. */
  364. int
  365. ldap_avl_apply( Avlnode *root, AVL_APPLY fn, void* arg, int stopflag, int type )
  366. {
  367. switch ( type ) {
  368. case AVL_INORDER:
  369. return( avl_inapply( root, fn, arg, stopflag ) );
  370. case AVL_PREORDER:
  371. return( avl_preapply( root, fn, arg, stopflag ) );
  372. case AVL_POSTORDER:
  373. return( avl_postapply( root, fn, arg, stopflag ) );
  374. default:
  375. fprintf( stderr, "Invalid traversal type %d\n", type );
  376. return( -1 );
  377. }
  378. /* NOTREACHED */
  379. }
  380. /*
  381. * ldap_avl_prefixapply - traverse avl tree root, applying function fprefix
  382. * to any nodes that match. fcmp is called with data as its first arg
  383. * and the current node's data as its second arg. it should return
  384. * 0 if they match, < 0 if data is less, and > 0 if data is greater.
  385. * the idea is to efficiently find all nodes that are prefixes of
  386. * some key... Like ldap_avl_apply, this routine also takes a stopflag
  387. * and will return prematurely if fmatch returns this value. Otherwise,
  388. * AVL_NOMORE is returned.
  389. */
  390. int
  391. ldap_avl_prefixapply(
  392. Avlnode *root,
  393. void* data,
  394. AVL_CMP fmatch,
  395. void* marg,
  396. AVL_CMP fcmp,
  397. void* carg,
  398. int stopflag
  399. )
  400. {
  401. int cmp;
  402. if ( root == 0 )
  403. return( AVL_NOMORE );
  404. cmp = (*fcmp)( data, root->avl_data /* , carg */);
  405. if ( cmp == 0 ) {
  406. if ( (*fmatch)( root->avl_data, marg ) == stopflag )
  407. return( stopflag );
  408. if ( root->avl_left != 0 )
  409. if ( ldap_avl_prefixapply( root->avl_left, data, fmatch,
  410. marg, fcmp, carg, stopflag ) == stopflag )
  411. return( stopflag );
  412. if ( root->avl_right != 0 )
  413. return( ldap_avl_prefixapply( root->avl_right, data, fmatch,
  414. marg, fcmp, carg, stopflag ) );
  415. else
  416. return( AVL_NOMORE );
  417. } else if ( cmp < 0 ) {
  418. if ( root->avl_left != 0 )
  419. return( ldap_avl_prefixapply( root->avl_left, data, fmatch,
  420. marg, fcmp, carg, stopflag ) );
  421. } else {
  422. if ( root->avl_right != 0 )
  423. return( ldap_avl_prefixapply( root->avl_right, data, fmatch,
  424. marg, fcmp, carg, stopflag ) );
  425. }
  426. return( AVL_NOMORE );
  427. }
  428. /*
  429. * ldap_avl_free -- traverse avltree root, freeing the memory it is using.
  430. * the dfree() is called to free the data portion of each node. The
  431. * number of items actually freed is returned.
  432. */
  433. int
  434. ldap_avl_free( Avlnode *root, AVL_FREE dfree )
  435. {
  436. int nleft, nright;
  437. if ( root == 0 )
  438. return( 0 );
  439. nleft = nright = 0;
  440. if ( root->avl_left != 0 )
  441. nleft = ldap_avl_free( root->avl_left, dfree );
  442. if ( root->avl_right != 0 )
  443. nright = ldap_avl_free( root->avl_right, dfree );
  444. if ( dfree )
  445. (*dfree)( root->avl_data );
  446. ber_memfree( root );
  447. return( nleft + nright + 1 );
  448. }
  449. /*
  450. * ldap_avl_find -- search avltree root for a node with data data. the function
  451. * cmp is used to compare things. it is called with data as its first arg
  452. * and the current node data as its second. it should return 0 if they match,
  453. * < 0 if arg1 is less than arg2 and > 0 if arg1 is greater than arg2.
  454. */
  455. Avlnode *
  456. ldap_avl_find2( Avlnode *root, const void *data, AVL_CMP fcmp )
  457. {
  458. int cmp;
  459. while ( root != 0 && (cmp = (*fcmp)( data, root->avl_data )) != 0 ) {
  460. cmp = cmp > 0;
  461. root = root->avl_link[cmp];
  462. }
  463. return root;
  464. }
  465. void*
  466. ldap_avl_find( Avlnode *root, const void* data, AVL_CMP fcmp )
  467. {
  468. int cmp;
  469. while ( root != 0 && (cmp = (*fcmp)( data, root->avl_data )) != 0 ) {
  470. cmp = cmp > 0;
  471. root = root->avl_link[cmp];
  472. }
  473. return( root ? root->avl_data : 0 );
  474. }
  475. /*
  476. * ldap_avl_find_lin -- search avltree root linearly for a node with data data.
  477. * the function cmp is used to compare things. it is called with data as its
  478. * first arg and the current node data as its second. it should return 0 if
  479. * they match, non-zero otherwise.
  480. */
  481. void*
  482. ldap_avl_find_lin( Avlnode *root, const void* data, AVL_CMP fcmp )
  483. {
  484. void* res;
  485. if ( root == 0 )
  486. return( NULL );
  487. if ( (*fcmp)( data, root->avl_data ) == 0 )
  488. return( root->avl_data );
  489. if ( root->avl_left != 0 )
  490. if ( (res = ldap_avl_find_lin( root->avl_left, data, fcmp ))
  491. != NULL )
  492. return( res );
  493. if ( root->avl_right == 0 )
  494. return( NULL );
  495. else
  496. return( ldap_avl_find_lin( root->avl_right, data, fcmp ) );
  497. }
  498. /* NON-REENTRANT INTERFACE */
  499. static void* *avl_list;
  500. static int avl_maxlist;
  501. static int ldap_avl_nextlist;
  502. #define AVL_GRABSIZE 100
  503. /* ARGSUSED */
  504. static int
  505. avl_buildlist( void* data, void* arg )
  506. {
  507. static int slots;
  508. if ( avl_list == (void* *) 0 ) {
  509. avl_list = (void* *) ber_memalloc(AVL_GRABSIZE * sizeof(void*));
  510. slots = AVL_GRABSIZE;
  511. avl_maxlist = 0;
  512. } else if ( avl_maxlist == slots ) {
  513. slots += AVL_GRABSIZE;
  514. avl_list = (void* *) ber_memrealloc( (char *) avl_list,
  515. (unsigned) slots * sizeof(void*));
  516. }
  517. avl_list[ avl_maxlist++ ] = data;
  518. return( 0 );
  519. }
  520. /*
  521. * ldap_avl_getfirst() and ldap_avl_getnext() are provided as alternate tree
  522. * traversal methods, to be used when a single function cannot be
  523. * provided to be called with every node in the tree. ldap_avl_getfirst()
  524. * traverses the tree and builds a linear list of all the nodes,
  525. * returning the first node. ldap_avl_getnext() returns the next thing
  526. * on the list built by ldap_avl_getfirst(). This means that ldap_avl_getfirst()
  527. * can take a while, and that the tree should not be messed with while
  528. * being traversed in this way, and that multiple traversals (even of
  529. * different trees) cannot be active at once.
  530. */
  531. void*
  532. ldap_avl_getfirst( Avlnode *root )
  533. {
  534. if ( avl_list ) {
  535. ber_memfree( (char *) avl_list);
  536. avl_list = (void* *) 0;
  537. }
  538. avl_maxlist = 0;
  539. ldap_avl_nextlist = 0;
  540. if ( root == 0 )
  541. return( 0 );
  542. (void) ldap_avl_apply( root, avl_buildlist, (void*) 0, -1, AVL_INORDER );
  543. return( avl_list[ ldap_avl_nextlist++ ] );
  544. }
  545. void*
  546. ldap_avl_getnext( void )
  547. {
  548. if ( avl_list == 0 )
  549. return( 0 );
  550. if ( ldap_avl_nextlist == avl_maxlist ) {
  551. ber_memfree( (void*) avl_list);
  552. avl_list = (void* *) 0;
  553. return( 0 );
  554. }
  555. return( avl_list[ ldap_avl_nextlist++ ] );
  556. }
  557. /* end non-reentrant code */
  558. int
  559. ldap_avl_dup_error( void* left, void* right )
  560. {
  561. return( -1 );
  562. }
  563. int
  564. ldap_avl_dup_ok( void* left, void* right )
  565. {
  566. return( 0 );
  567. }