skip-list.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. /*
  2. * Copyright 2021
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. *
  17. * SPDX-License-Identifier: GPL-3.0+
  18. * License-Filename: LICENSE
  19. *
  20. */
  21. /* skip list algoithm with same usage as GNU GCC compiler splay-tree.c, see also wikipedia for skiplist */
  22. /**
  23. * @file: skip-list.c
  24. */
  25. #include "config.h"
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include "skip-list.h"
  30. #include "dpmem.h"
  31. /* here wrapping to custom malloc/free can be set */
  32. static inline void *skip_list_malloc(size_t n)
  33. {
  34. return (dp_calloc(1, n));
  35. }
  36. static inline void *skip_list_free(void *ptr)
  37. {
  38. void *ptr2 = NULL;
  39. if (ptr) {
  40. ptr2 = dp_free(ptr);
  41. if (ptr2) {
  42. }
  43. }
  44. return (NULL);
  45. }
  46. /* forward decl. */
  47. static skip_list_node skip_list_create_node(int level, skip_list_key key, skip_list_value val);
  48. static int skip_list_randomlevel(void);
  49. /* delete whole sp tree */
  50. skip_list skip_list_delete(skip_list sp)
  51. {
  52. skip_list_node q = (skip_list_node) 0;
  53. skip_list_node next = (skip_list_node) 0;
  54. if (sp == (skip_list) 0) {
  55. return ((skip_list) 0);
  56. }
  57. if (sp->head) {
  58. q = sp->head;
  59. while (q) {
  60. next = q->next[0];
  61. if (q->value) {
  62. if (sp->delete_value) {
  63. (*sp->delete_value) (q->value);
  64. }
  65. }
  66. if (q->key) {
  67. if (sp->delete_key) {
  68. (*sp->delete_key) (q->key);
  69. }
  70. }
  71. q = (skip_list_node) skip_list_free(q);
  72. /* q is never read */
  73. if (q) {
  74. }
  75. q = next;
  76. }
  77. }
  78. return ((skip_list) skip_list_free(sp));
  79. }
  80. /* Allocate a new skip list tree, using COMPARE_FN to compare nodes,
  81. DELETE_KEY_FN to deallocate keys, and DELETE_VALUE_FN to deallocate
  82. values. */
  83. skip_list
  84. skip_list_new(skip_list_compare_fn compare_fn, skip_list_delete_key_fn delete_key_fn, skip_list_delete_value_fn delete_value_fn)
  85. {
  86. skip_list sp = (skip_list) 0;
  87. skip_list_node h = (skip_list_node) 0;
  88. int i = 0;
  89. /* there must be a compare function, the free() functions are optional */
  90. if (compare_fn == (skip_list_compare_fn) 0) {
  91. return ((skip_list) 0);
  92. }
  93. sp = (skip_list) skip_list_malloc(sizeof(struct skip_list_t));
  94. sp->level = 0;
  95. h = skip_list_create_node((SKIP_LIST_MAX_LEVEL - 1), 0, 0);
  96. sp->head = h;
  97. for (i = 0; i < SKIP_LIST_MAX_LEVEL; ++i) {
  98. h->next[i] = (skip_list_node) 0;
  99. }
  100. /* The comparision function. */
  101. sp->comp = compare_fn;
  102. /* The deallocate-key function. NULL if no cleanup is necessary. */
  103. sp->delete_key = delete_key_fn;
  104. /* The deallocate-value function. NULL if no cleanup is necessary. */
  105. sp->delete_value = delete_value_fn;
  106. return ((skip_list) sp);
  107. }
  108. /* Insert a new node (associating KEY with DATA) into SP. If a
  109. previous node with the indicated KEY exists, its data is not replaced
  110. with the new value. */
  111. void skip_list_insert(skip_list sp, skip_list_key key, skip_list_value value)
  112. {
  113. skip_list_node update[SKIP_LIST_MAX_LEVEL];
  114. skip_list_node q = (skip_list_node) 0;
  115. skip_list_node p = (skip_list_node) 0;
  116. int comparison = 0;
  117. int level = 0;
  118. int i = 0;
  119. if (sp == (skip_list) 0) {
  120. /* no tree */
  121. return;
  122. }
  123. if (sp->head == (skip_list_node) 0) {
  124. return;
  125. }
  126. p = sp->head;
  127. for (i = (sp->level) - 1; i >= 0; --i) {
  128. while ((q = p->next[i])) {
  129. comparison = (*sp->comp) (q->key, key);
  130. /* check if q->key >= key */
  131. if (comparison >= 0) {
  132. break;
  133. }
  134. /* here if q->key < key */
  135. p = q;
  136. }
  137. update[i] = p;
  138. }
  139. /* check if key already exist */
  140. if (q) {
  141. if (q->key == key) {
  142. if (0) {
  143. /* if found, update with new value */
  144. if (q->value) {
  145. if (sp->delete_value) {
  146. (*sp->delete_value) (q->value);
  147. }
  148. }
  149. q->value = value;
  150. }
  151. return;
  152. }
  153. }
  154. level = skip_list_randomlevel();
  155. if (level > sp->level) {
  156. for (i = sp->level; i < level; ++i) {
  157. update[i] = sp->head;
  158. }
  159. sp->level = level;
  160. }
  161. q = skip_list_create_node(level, key, value);
  162. for (i = (level - 1); i >= 0; --i) {
  163. q->next[i] = update[i]->next[i];
  164. update[i]->next[i] = q;
  165. }
  166. return;
  167. }
  168. /* Remove KEY from SP. It is not an error if it did not exist. */
  169. void skip_list_remove(skip_list sp, skip_list_key key)
  170. {
  171. skip_list_node update[SKIP_LIST_MAX_LEVEL];
  172. skip_list_node q = (skip_list_node) 0;
  173. skip_list_node p = (skip_list_node) 0;
  174. int comparison = 0;
  175. int i = 0;
  176. if (sp == (skip_list) 0) {
  177. /* no tree */
  178. return;
  179. }
  180. if (sp->head == (skip_list_node) 0) {
  181. return;
  182. }
  183. p = sp->head;
  184. for (i = (sp->level) - 1; i >= 0; --i) {
  185. while ((q = p->next[i])) {
  186. comparison = (*sp->comp) (q->key, key);
  187. /* check if q->key >= key */
  188. if (comparison >= 0) {
  189. break;
  190. }
  191. /* here if q->key < key */
  192. p = q;
  193. }
  194. update[i] = p;
  195. }
  196. if (q == (skip_list_node) 0) {
  197. return;
  198. }
  199. if (q->key != key) {
  200. return;
  201. }
  202. for (i = (sp->level - 1); i >= 0; --i) {
  203. if (update[i]->next[i] == q) {
  204. update[i]->next[i] = q->next[i];
  205. if (sp->head->next[i] == (skip_list_node) 0) {
  206. sp->level--;
  207. }
  208. }
  209. }
  210. if (q->value) {
  211. if (sp->delete_value) {
  212. (*sp->delete_value) (q->value);
  213. }
  214. }
  215. if (q->key) {
  216. if (sp->delete_key) {
  217. (*sp->delete_key) (q->key);
  218. }
  219. }
  220. q = (skip_list_node) skip_list_free(q);
  221. /* q is never read */
  222. if (q) {
  223. }
  224. return;
  225. }
  226. /* Lookup KEY in SP, returning VALUE if present, and NULL
  227. otherwise. */
  228. skip_list_node skip_list_lookup(skip_list sp, skip_list_key key)
  229. {
  230. skip_list_node q = (skip_list_node) 0;
  231. skip_list_node p = (skip_list_node) 0;
  232. int comparison = 0;
  233. int i = 0;
  234. if (sp == (skip_list) 0) {
  235. /* no tree */
  236. return ((skip_list_node) 0);
  237. }
  238. if (sp->head == (skip_list_node) 0) {
  239. return ((skip_list_node) 0);
  240. }
  241. p = sp->head;
  242. for (i = (sp->level - 1); i >= 0; --i) {
  243. while ((q = p->next[i])) {
  244. comparison = (*sp->comp) (q->key, key);
  245. /* check if q->key >= key */
  246. if (comparison >= 0) {
  247. break;
  248. }
  249. /* here if q->key < key */
  250. p = q;
  251. }
  252. }
  253. if (q) {
  254. if (q->key == key) {
  255. return ((skip_list_node) q);
  256. }
  257. }
  258. /* not found */
  259. return ((skip_list_node) 0);
  260. }
  261. /* free() wrappers to free key/value */
  262. void skip_list_free_value(skip_list_value value)
  263. {
  264. void *v2 = NULL;
  265. if (value) {
  266. v2 = skip_list_free((void *)value);
  267. if (v2) {
  268. }
  269. }
  270. return;
  271. }
  272. void skip_list_free_key(skip_list_key key)
  273. {
  274. void *k = NULL;
  275. if (key) {
  276. k = skip_list_free((void *)key);
  277. if (k) {
  278. }
  279. }
  280. return;
  281. }
  282. /* comparison function, treating the keys as ints. */
  283. int skip_list_compare_ints(skip_list_key k1, skip_list_key k2)
  284. {
  285. if ((int)k1 < (int)k2) {
  286. return ((int)-1);
  287. } else if ((int)k1 > (int)k2) {
  288. return (1);
  289. } else {
  290. return (0);
  291. }
  292. }
  293. /* comparison function, treating the keys as pointers.
  294. Note this is possibly not portable on all systems according to standards
  295. and may have undefined results. there seems no good solution for this.
  296. (a char datatype does not have to be a single byte in c for example)
  297. */
  298. int skip_list_compare_pointers(skip_list_key k1, skip_list_key k2)
  299. {
  300. /* 0==0 */
  301. if ((k1 == (skip_list_key) 0) && (k2 == (skip_list_key) 0)) {
  302. return (0);
  303. }
  304. /* possible undefined results at this, says the c standard. has to be understood as (signed char *) */
  305. if ((char *)k1 < (char *)k2) {
  306. return ((int)-1);
  307. } else if ((char *)k1 > (char *)k2) {
  308. return (1);
  309. } else {
  310. return (0);
  311. }
  312. }
  313. /* Comparison function for a skip list in which the keys are strings.
  314. K1 and K2 have the dynamic type "const char *". Returns <0, 0, or
  315. >0 to indicate whether K1 is less than, equal to, or greater than
  316. K2, respectively.
  317. similar issues here when as compare pointers and c portable src.
  318. */
  319. int skip_list_compare_strings(skip_list_key k1, skip_list_key k2)
  320. {
  321. const char *s1 = (const char *)k1;
  322. const char *s2 = (const char *)k2;
  323. int ret = 0;
  324. if ((k1 == (skip_list_key) 0) && (k2 == (skip_list_key) 0)) {
  325. return (0);
  326. }
  327. if (s1 == (const char *)0) {
  328. /* to avoid crashes only */
  329. return (0);
  330. }
  331. if (s2 == (const char *)0) {
  332. /* to avoid crashes only */
  333. return (0);
  334. }
  335. /* check if same pointer. possible not portable c. */
  336. if (s1 == s2) {
  337. return (0);
  338. }
  339. ret = strcmp(s1, s2);
  340. return ((int)ret);
  341. }
  342. /* */
  343. static skip_list_node skip_list_create_node(int level, skip_list_key key, skip_list_value val)
  344. {
  345. skip_list_node p = (skip_list_node) 0;
  346. p = (skip_list_node) skip_list_malloc((sizeof(struct skip_list_node_n) + level * sizeof(skip_list_node)));
  347. p->key = key;
  348. p->value = val;
  349. return ((skip_list_node) p);
  350. }
  351. /* */
  352. static int skip_list_randomlevel(void)
  353. {
  354. int level = 1;
  355. double d = 0.0;
  356. int c = 0;
  357. for (;;) {
  358. c = rand();
  359. d = (double)c;
  360. if ((d / SKIP_LIST_MAX_LEVEL) < 0.50) {
  361. level++;
  362. if (level > SKIP_LIST_MAX_LEVEL) {
  363. break;
  364. }
  365. }
  366. }
  367. if (level > SKIP_LIST_MAX_LEVEL) {
  368. level = SKIP_LIST_MAX_LEVEL;
  369. }
  370. return level;
  371. }
  372. /* end. */