tavl.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  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 2005-2022 The OpenLDAP Foundation.
  6. * Portions Copyright (c) 2005 by Howard Chu, Symas Corp.
  7. * All rights reserved.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted only as authorized by the OpenLDAP
  11. * Public License.
  12. *
  13. * A copy of this license is available in the file LICENSE in the
  14. * top-level directory of the distribution or, alternatively, at
  15. * <http://www.OpenLDAP.org/license.html>.
  16. */
  17. /* ACKNOWLEDGEMENTS:
  18. * This work was initially developed by Howard Chu for inclusion
  19. * in OpenLDAP software.
  20. */
  21. #include "portable.h"
  22. #include <limits.h>
  23. #include <stdio.h>
  24. #include <ac/stdlib.h>
  25. #ifdef CSRIMALLOC
  26. #define ber_memalloc malloc
  27. #define ber_memrealloc realloc
  28. #define ber_memfree free
  29. #else
  30. #include "lber.h"
  31. #endif
  32. #define AVL_INTERNAL
  33. #include "ldap_avl.h"
  34. /* Maximum tree depth this host's address space could support */
  35. #define MAX_TREE_DEPTH (sizeof(void *) * CHAR_BIT)
  36. static const int avl_bfs[] = {LH, RH};
  37. /*
  38. * Threaded AVL trees - for fast in-order traversal of nodes.
  39. */
  40. /*
  41. * ldap_tavl_insert -- insert a node containing data data into the avl tree
  42. * with root root. fcmp is a function to call to compare the data portion
  43. * of two nodes. it should take two arguments and return <, >, or == 0,
  44. * depending on whether its first argument is <, >, or == its second
  45. * argument (like strcmp, e.g.). fdup is a function to call when a duplicate
  46. * node is inserted. it should return 0, or -1 and its return value
  47. * will be the return value from ldap_avl_insert in the case of a duplicate node.
  48. * the function will be called with the original node's data as its first
  49. * argument and with the incoming duplicate node's data as its second
  50. * argument. this could be used, for example, to keep a count with each
  51. * node.
  52. *
  53. * NOTE: this routine may malloc memory
  54. */
  55. int
  56. ldap_tavl_insert( TAvlnode ** root, void *data, AVL_CMP fcmp, AVL_DUP fdup )
  57. {
  58. TAvlnode *t, *p, *s, *q, *r;
  59. int a, cmp, ncmp;
  60. if ( *root == NULL ) {
  61. if (( r = (TAvlnode *) ber_memalloc( sizeof( TAvlnode ))) == NULL ) {
  62. return( -1 );
  63. }
  64. r->avl_link[0] = r->avl_link[1] = NULL;
  65. r->avl_data = data;
  66. r->avl_bf = EH;
  67. r->avl_bits[0] = r->avl_bits[1] = AVL_THREAD;
  68. *root = r;
  69. return( 0 );
  70. }
  71. t = NULL;
  72. s = p = *root;
  73. /* find insertion point */
  74. while (1) {
  75. cmp = fcmp( data, p->avl_data );
  76. if ( cmp == 0 )
  77. return (*fdup)( p->avl_data, data );
  78. cmp = (cmp > 0);
  79. q = ldap_avl_child( p, cmp );
  80. if (q == NULL) {
  81. /* insert */
  82. if (( q = (TAvlnode *) ber_memalloc( sizeof( TAvlnode ))) == NULL ) {
  83. return( -1 );
  84. }
  85. q->avl_link[cmp] = p->avl_link[cmp];
  86. q->avl_link[!cmp] = p;
  87. q->avl_data = data;
  88. q->avl_bf = EH;
  89. q->avl_bits[0] = q->avl_bits[1] = AVL_THREAD;
  90. p->avl_link[cmp] = q;
  91. p->avl_bits[cmp] = AVL_CHILD;
  92. break;
  93. } else if ( q->avl_bf ) {
  94. t = p;
  95. s = q;
  96. }
  97. p = q;
  98. }
  99. /* adjust balance factors */
  100. cmp = fcmp( data, s->avl_data ) > 0;
  101. r = p = s->avl_link[cmp];
  102. a = avl_bfs[cmp];
  103. while ( p != q ) {
  104. cmp = fcmp( data, p->avl_data ) > 0;
  105. p->avl_bf = avl_bfs[cmp];
  106. p = p->avl_link[cmp];
  107. }
  108. /* checks and balances */
  109. if ( s->avl_bf == EH ) {
  110. s->avl_bf = a;
  111. return 0;
  112. } else if ( s->avl_bf == -a ) {
  113. s->avl_bf = EH;
  114. return 0;
  115. } else if ( s->avl_bf == a ) {
  116. cmp = (a > 0);
  117. ncmp = !cmp;
  118. if ( r->avl_bf == a ) {
  119. /* single rotation */
  120. p = r;
  121. if ( r->avl_bits[ncmp] == AVL_THREAD ) {
  122. r->avl_bits[ncmp] = AVL_CHILD;
  123. s->avl_bits[cmp] = AVL_THREAD;
  124. } else {
  125. s->avl_link[cmp] = r->avl_link[ncmp];
  126. r->avl_link[ncmp] = s;
  127. }
  128. s->avl_bf = 0;
  129. r->avl_bf = 0;
  130. } else if ( r->avl_bf == -a ) {
  131. /* double rotation */
  132. p = r->avl_link[ncmp];
  133. if ( p->avl_bits[cmp] == AVL_THREAD ) {
  134. p->avl_bits[cmp] = AVL_CHILD;
  135. r->avl_bits[ncmp] = AVL_THREAD;
  136. } else {
  137. r->avl_link[ncmp] = p->avl_link[cmp];
  138. p->avl_link[cmp] = r;
  139. }
  140. if ( p->avl_bits[ncmp] == AVL_THREAD ) {
  141. p->avl_bits[ncmp] = AVL_CHILD;
  142. s->avl_link[cmp] = p;
  143. s->avl_bits[cmp] = AVL_THREAD;
  144. } else {
  145. s->avl_link[cmp] = p->avl_link[ncmp];
  146. p->avl_link[ncmp] = s;
  147. }
  148. if ( p->avl_bf == a ) {
  149. s->avl_bf = -a;
  150. r->avl_bf = 0;
  151. } else if ( p->avl_bf == -a ) {
  152. s->avl_bf = 0;
  153. r->avl_bf = a;
  154. } else {
  155. s->avl_bf = 0;
  156. r->avl_bf = 0;
  157. }
  158. p->avl_bf = 0;
  159. }
  160. /* Update parent */
  161. if ( t == NULL )
  162. *root = p;
  163. else if ( s == t->avl_right )
  164. t->avl_right = p;
  165. else
  166. t->avl_left = p;
  167. }
  168. return 0;
  169. }
  170. void*
  171. ldap_tavl_delete( TAvlnode **root, void* data, AVL_CMP fcmp )
  172. {
  173. TAvlnode *p, *q, *r, *top;
  174. int side, side_bf, shorter, nside = -1;
  175. /* parent stack */
  176. TAvlnode *pptr[MAX_TREE_DEPTH];
  177. unsigned char pdir[MAX_TREE_DEPTH];
  178. int depth = 0;
  179. if ( *root == NULL )
  180. return NULL;
  181. p = *root;
  182. while (1) {
  183. side = fcmp( data, p->avl_data );
  184. if ( !side )
  185. break;
  186. side = ( side > 0 );
  187. pdir[depth] = side;
  188. pptr[depth++] = p;
  189. if ( p->avl_bits[side] == AVL_THREAD )
  190. return NULL;
  191. p = p->avl_link[side];
  192. }
  193. data = p->avl_data;
  194. /* If this node has two children, swap so we are deleting a node with
  195. * at most one child.
  196. */
  197. if ( p->avl_bits[0] == AVL_CHILD && p->avl_bits[1] == AVL_CHILD &&
  198. p->avl_link[0] && p->avl_link[1] ) {
  199. /* find the immediate predecessor <q> */
  200. q = p->avl_link[0];
  201. side = depth;
  202. pdir[depth++] = 0;
  203. while (q->avl_bits[1] == AVL_CHILD && q->avl_link[1]) {
  204. pdir[depth] = 1;
  205. pptr[depth++] = q;
  206. q = q->avl_link[1];
  207. }
  208. /* swap links */
  209. r = p->avl_link[0];
  210. p->avl_link[0] = q->avl_link[0];
  211. q->avl_link[0] = r;
  212. q->avl_link[1] = p->avl_link[1];
  213. p->avl_link[1] = q;
  214. p->avl_bits[0] = q->avl_bits[0];
  215. p->avl_bits[1] = q->avl_bits[1];
  216. q->avl_bits[0] = q->avl_bits[1] = AVL_CHILD;
  217. q->avl_bf = p->avl_bf;
  218. /* fix stack positions: old parent of p points to q */
  219. pptr[side] = q;
  220. if ( side ) {
  221. r = pptr[side-1];
  222. r->avl_link[pdir[side-1]] = q;
  223. } else {
  224. *root = q;
  225. }
  226. /* new parent of p points to p */
  227. if ( depth-side > 1 ) {
  228. r = pptr[depth-1];
  229. r->avl_link[1] = p;
  230. } else {
  231. q->avl_link[0] = p;
  232. }
  233. /* fix right subtree: successor of p points to q */
  234. r = q->avl_link[1];
  235. while ( r->avl_bits[0] == AVL_CHILD && r->avl_link[0] )
  236. r = r->avl_link[0];
  237. r->avl_link[0] = q;
  238. }
  239. /* now <p> has at most one child, get it */
  240. if ( p->avl_link[0] && p->avl_bits[0] == AVL_CHILD ) {
  241. q = p->avl_link[0];
  242. /* Preserve thread continuity */
  243. r = p->avl_link[1];
  244. nside = 1;
  245. } else if ( p->avl_link[1] && p->avl_bits[1] == AVL_CHILD ) {
  246. q = p->avl_link[1];
  247. r = p->avl_link[0];
  248. nside = 0;
  249. } else {
  250. q = NULL;
  251. if ( depth > 0 )
  252. r = p->avl_link[pdir[depth-1]];
  253. else
  254. r = NULL;
  255. }
  256. ber_memfree( p );
  257. /* Update child thread */
  258. if ( q ) {
  259. for ( ; q->avl_bits[nside] == AVL_CHILD && q->avl_link[nside];
  260. q = q->avl_link[nside] ) ;
  261. q->avl_link[nside] = r;
  262. }
  263. if ( !depth ) {
  264. *root = q;
  265. return data;
  266. }
  267. /* set the child into p's parent */
  268. depth--;
  269. p = pptr[depth];
  270. side = pdir[depth];
  271. p->avl_link[side] = q;
  272. if ( !q ) {
  273. p->avl_bits[side] = AVL_THREAD;
  274. p->avl_link[side] = r;
  275. }
  276. top = NULL;
  277. shorter = 1;
  278. while ( shorter ) {
  279. p = pptr[depth];
  280. side = pdir[depth];
  281. nside = !side;
  282. side_bf = avl_bfs[side];
  283. /* case 1: height unchanged */
  284. if ( p->avl_bf == EH ) {
  285. /* Tree is now heavier on opposite side */
  286. p->avl_bf = avl_bfs[nside];
  287. shorter = 0;
  288. } else if ( p->avl_bf == side_bf ) {
  289. /* case 2: taller subtree shortened, height reduced */
  290. p->avl_bf = EH;
  291. } else {
  292. /* case 3: shorter subtree shortened */
  293. if ( depth )
  294. top = pptr[depth-1]; /* p->parent; */
  295. else
  296. top = NULL;
  297. /* set <q> to the taller of the two subtrees of <p> */
  298. q = p->avl_link[nside];
  299. if ( q->avl_bf == EH ) {
  300. /* case 3a: height unchanged, single rotate */
  301. if ( q->avl_bits[side] == AVL_THREAD ) {
  302. q->avl_bits[side] = AVL_CHILD;
  303. p->avl_bits[nside] = AVL_THREAD;
  304. } else {
  305. p->avl_link[nside] = q->avl_link[side];
  306. q->avl_link[side] = p;
  307. }
  308. shorter = 0;
  309. q->avl_bf = side_bf;
  310. p->avl_bf = (- side_bf);
  311. } else if ( q->avl_bf == p->avl_bf ) {
  312. /* case 3b: height reduced, single rotate */
  313. if ( q->avl_bits[side] == AVL_THREAD ) {
  314. q->avl_bits[side] = AVL_CHILD;
  315. p->avl_bits[nside] = AVL_THREAD;
  316. } else {
  317. p->avl_link[nside] = q->avl_link[side];
  318. q->avl_link[side] = p;
  319. }
  320. shorter = 1;
  321. q->avl_bf = EH;
  322. p->avl_bf = EH;
  323. } else {
  324. /* case 3c: height reduced, balance factors opposite */
  325. r = q->avl_link[side];
  326. if ( r->avl_bits[nside] == AVL_THREAD ) {
  327. r->avl_bits[nside] = AVL_CHILD;
  328. q->avl_bits[side] = AVL_THREAD;
  329. } else {
  330. q->avl_link[side] = r->avl_link[nside];
  331. r->avl_link[nside] = q;
  332. }
  333. if ( r->avl_bits[side] == AVL_THREAD ) {
  334. r->avl_bits[side] = AVL_CHILD;
  335. p->avl_bits[nside] = AVL_THREAD;
  336. p->avl_link[nside] = r;
  337. } else {
  338. p->avl_link[nside] = r->avl_link[side];
  339. r->avl_link[side] = p;
  340. }
  341. if ( r->avl_bf == side_bf ) {
  342. q->avl_bf = (- side_bf);
  343. p->avl_bf = EH;
  344. } else if ( r->avl_bf == (- side_bf)) {
  345. q->avl_bf = EH;
  346. p->avl_bf = side_bf;
  347. } else {
  348. q->avl_bf = EH;
  349. p->avl_bf = EH;
  350. }
  351. r->avl_bf = EH;
  352. q = r;
  353. }
  354. /* a rotation has caused <q> (or <r> in case 3c) to become
  355. * the root. let <p>'s former parent know this.
  356. */
  357. if ( top == NULL ) {
  358. *root = q;
  359. } else if (top->avl_link[0] == p) {
  360. top->avl_link[0] = q;
  361. } else {
  362. top->avl_link[1] = q;
  363. }
  364. /* end case 3 */
  365. p = q;
  366. }
  367. if ( !depth )
  368. break;
  369. depth--;
  370. } /* end while(shorter) */
  371. return data;
  372. }
  373. /*
  374. * ldap_tavl_free -- traverse avltree root, freeing the memory it is using.
  375. * the dfree() is called to free the data portion of each node. The
  376. * number of items actually freed is returned.
  377. */
  378. int
  379. ldap_tavl_free( TAvlnode *root, AVL_FREE dfree )
  380. {
  381. int nleft, nright;
  382. if ( root == 0 )
  383. return( 0 );
  384. nleft = ldap_tavl_free( ldap_avl_lchild( root ), dfree );
  385. nright = ldap_tavl_free( ldap_avl_rchild( root ), dfree );
  386. if ( dfree )
  387. (*dfree)( root->avl_data );
  388. ber_memfree( root );
  389. return( nleft + nright + 1 );
  390. }
  391. /*
  392. * ldap_tavl_find -- search avltree root for a node with data data. the function
  393. * cmp is used to compare things. it is called with data as its first arg
  394. * and the current node data as its second. it should return 0 if they match,
  395. * < 0 if arg1 is less than arg2 and > 0 if arg1 is greater than arg2.
  396. */
  397. /*
  398. * ldap_tavl_find2 - returns TAvlnode instead of data pointer.
  399. * ldap_tavl_find3 - as above, but returns TAvlnode even if no match is found.
  400. * also set *ret = last comparison result, or -1 if root == NULL.
  401. */
  402. TAvlnode *
  403. ldap_tavl_find3( TAvlnode *root, const void *data, AVL_CMP fcmp, int *ret )
  404. {
  405. int cmp = -1, dir;
  406. TAvlnode *prev = root;
  407. while ( root != 0 && (cmp = (*fcmp)( data, root->avl_data )) != 0 ) {
  408. prev = root;
  409. dir = cmp > 0;
  410. root = ldap_avl_child( root, dir );
  411. }
  412. *ret = cmp;
  413. return root ? root : prev;
  414. }
  415. TAvlnode *
  416. ldap_tavl_find2( TAvlnode *root, const void *data, AVL_CMP fcmp )
  417. {
  418. int cmp;
  419. while ( root != 0 && (cmp = (*fcmp)( data, root->avl_data )) != 0 ) {
  420. cmp = cmp > 0;
  421. root = ldap_avl_child( root, cmp );
  422. }
  423. return root;
  424. }
  425. void*
  426. ldap_tavl_find( TAvlnode *root, const void* data, AVL_CMP fcmp )
  427. {
  428. int cmp;
  429. while ( root != 0 && (cmp = (*fcmp)( data, root->avl_data )) != 0 ) {
  430. cmp = cmp > 0;
  431. root = ldap_avl_child( root, cmp );
  432. }
  433. return( root ? root->avl_data : 0 );
  434. }
  435. /* Return the leftmost or rightmost node in the tree */
  436. TAvlnode *
  437. ldap_tavl_end( TAvlnode *root, int dir )
  438. {
  439. if ( root ) {
  440. while ( root->avl_bits[dir] == AVL_CHILD )
  441. root = root->avl_link[dir];
  442. }
  443. return root;
  444. }
  445. /* Return the next node in the given direction */
  446. TAvlnode *
  447. ldap_tavl_next( TAvlnode *root, int dir )
  448. {
  449. if ( root ) {
  450. int c = root->avl_bits[dir];
  451. root = root->avl_link[dir];
  452. if ( c == AVL_CHILD ) {
  453. dir ^= 1;
  454. while ( root->avl_bits[dir] == AVL_CHILD )
  455. root = root->avl_link[dir];
  456. }
  457. }
  458. return root;
  459. }