collections.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548
  1. /*
  2. * Andrea Di Biagio
  3. * Politecnico di Milano, 2007
  4. *
  5. * collections.c
  6. * Formal Languages & Compilers Machine, 2007/2008
  7. *
  8. */
  9. #include <stdlib.h>
  10. #include <assert.h>
  11. #include "collections.h"
  12. /* function prototypes */
  13. static t_list * newElement(void *data);
  14. /* remove the first element of the list. Returns the new
  15. * head of the list */
  16. t_list * removeFirst(t_list *list)
  17. {
  18. t_list *first_elem;
  19. if (list == NULL)
  20. return NULL;
  21. first_elem = list;
  22. list = LNEXT(list);
  23. if (list != NULL)
  24. SET_PREV(list, NULL);
  25. _FREE_FUNCTION(first_elem);
  26. /* postconditions: return the new head of the list */
  27. return list;
  28. }
  29. /* add an element `data' to the list `list' at position `pos'. If pos is negative
  30. * , or is larger than the number of elements in the list, the new element is
  31. * added on to the end of the list. Function `addElement' returns a pointer
  32. * to the new head of the list */
  33. t_list * addElement(t_list *list, void * data, int pos)
  34. {
  35. t_list *result;
  36. t_list *current_elem;
  37. t_list *last_elem;
  38. int current_pos;
  39. /* initialize the value of `result' */
  40. result = newElement(data);
  41. if (list == NULL)
  42. return result;
  43. if (pos == 0)
  44. {
  45. /* update the control informations */
  46. SET_NEXT(result, list);
  47. SET_PREV(list, result);
  48. /* return the new head of the list */
  49. return result;
  50. }
  51. /* retrieve the last element of the list */
  52. last_elem = getLastElement(list);
  53. assert(last_elem != NULL);
  54. if (pos < 0)
  55. {
  56. /* update the control informations */
  57. SET_NEXT(last_elem, result);
  58. SET_PREV(result, last_elem);
  59. /* update the value of result */
  60. return list;
  61. }
  62. /* `pos' is a positive integer */
  63. current_pos = 0;
  64. current_elem = list;
  65. while(current_pos < pos)
  66. {
  67. if (current_elem == last_elem)
  68. {
  69. /* update the control informations */
  70. SET_NEXT(last_elem, result);
  71. SET_PREV(result, last_elem);
  72. /* update the value of result */
  73. return list;
  74. }
  75. /* update the loop informations */
  76. current_elem = LNEXT(current_elem);
  77. current_pos++;
  78. }
  79. /* assertions */
  80. assert(current_elem != NULL);
  81. /* update the control informations */
  82. SET_NEXT(result, current_elem);
  83. SET_PREV(result, LPREV(current_elem));
  84. SET_NEXT(LPREV(current_elem), result);
  85. SET_PREV(current_elem, result);
  86. /* return the new head of the list */
  87. return list;
  88. }
  89. /* add an element at the beginning of the list */
  90. t_list * addFirst(t_list *list, void * data)
  91. {
  92. t_list *result;
  93. /* initialize the value of `result' */
  94. result = newElement(data);
  95. if (list == NULL)
  96. return result;
  97. /* postconditions */
  98. SET_PREV(list, result);
  99. SET_NEXT(result, list);
  100. /* return the new head of the list */
  101. return result;
  102. }
  103. /* add an element to the end of the list */
  104. t_list * addLast(t_list *list, void * data)
  105. {
  106. /* call the `addElement' */
  107. return addElement(list, data, -1);
  108. }
  109. /* remove an element from the list */
  110. t_list * removeElement(t_list *list, void * data)
  111. {
  112. t_list *current_elem;
  113. /* preconditions: the list shouldn't be empty */
  114. if (list == NULL)
  115. return NULL;
  116. /* intialize the value of `current_elem' */
  117. current_elem = list;
  118. while ( (current_elem != NULL)
  119. && (LDATA(current_elem) != data))
  120. {
  121. current_elem = LNEXT(current_elem);
  122. }
  123. /* the value hasn't been found */
  124. if (current_elem == NULL)
  125. return list;
  126. /* the value is found */
  127. if (LPREV(current_elem) != NULL)
  128. {
  129. SET_NEXT(LPREV(current_elem), LNEXT(current_elem));
  130. if (LNEXT(current_elem) != NULL)
  131. SET_PREV(LNEXT(current_elem), LPREV(current_elem));
  132. _FREE_FUNCTION(current_elem);
  133. }
  134. else
  135. {
  136. /* check the preconditions */
  137. assert(list == current_elem);
  138. if (LNEXT(current_elem) != NULL)
  139. {
  140. SET_PREV(LNEXT(current_elem), NULL);
  141. /* update the new head of the list */
  142. list = LNEXT(current_elem);
  143. }
  144. else
  145. list = NULL;
  146. _FREE_FUNCTION(current_elem);
  147. }
  148. /* postconditions: return the new head of the list */
  149. return list;
  150. }
  151. /* remove all the elements of a list */
  152. void freeList(t_list *list)
  153. {
  154. /* verify the preconditions */
  155. if (list == NULL)
  156. return;
  157. /* recursively call the freeList */
  158. freeList(LNEXT(list));
  159. /* deallocate memory for the current element of the list */
  160. _FREE_FUNCTION(list);
  161. }
  162. t_list * newElement(void *data)
  163. {
  164. t_list * result;
  165. /* create an instance of t_list in memory */
  166. result = (t_list *) _ALLOC_FUNCTION(sizeof(t_list));
  167. /* verify the out of memory condition */
  168. if (result == NULL)
  169. {
  170. fprintf(stderr, "COLLECTIONS.C:: _ALLOC_FUNCTION returned a NULL pointer \n");
  171. abort();
  172. }
  173. /* set the internal value of the just created t_list element */
  174. SET_DATA(result, data);
  175. SET_PREV(result, NULL);
  176. SET_NEXT(result, NULL);
  177. /* postconditions : return the element */
  178. return result;
  179. }
  180. t_list * getLastElement(t_list *list)
  181. {
  182. /* preconditions */
  183. if (list == NULL)
  184. return NULL;
  185. /* test if the current element is the last element of the list */
  186. if (LNEXT(list) == NULL)
  187. return list;
  188. /* recursively call the getLastElement on the next item of the list */
  189. return getLastElement(LNEXT(list));
  190. }
  191. /* remove a link from the list `list' */
  192. extern t_list * removeElementLink(t_list *list, t_list *element)
  193. {
  194. t_list *current_elem;
  195. /* preconditions */
  196. if (list == NULL || element == NULL)
  197. return list;
  198. if ((LPREV(element) == NULL) && (element != list))
  199. return list;
  200. /* intialize the value of `current_elem' */
  201. current_elem = list;
  202. while( (LDATA(current_elem) != LDATA(element))
  203. || (LPREV(current_elem) != LPREV(element))
  204. || (LNEXT(current_elem) != LNEXT(element)) )
  205. {
  206. /* retrieve the next element from the list */
  207. current_elem = LNEXT(current_elem);
  208. /* test if we reached the end of the list */
  209. if (current_elem == NULL)
  210. return list;
  211. }
  212. if (LPREV(element) == NULL)
  213. {
  214. assert(list == element);
  215. if (LNEXT(element) != NULL)
  216. {
  217. list = LNEXT(element);
  218. SET_PREV(LNEXT(element), NULL);
  219. }
  220. else
  221. list = NULL;
  222. /* remove the allocated memory of element */
  223. _FREE_FUNCTION(element);
  224. return list;
  225. }
  226. /* we found the element */
  227. if (LPREV(element) != NULL)
  228. {
  229. /* we found the element, and it is the top of the list */
  230. SET_NEXT(LPREV(element), LNEXT(element));
  231. }
  232. if (LNEXT(element) != NULL)
  233. SET_PREV(LNEXT(element), LPREV(element));
  234. /* remove the allocated memory of element */
  235. _FREE_FUNCTION(element);
  236. /* return the new top of the list */
  237. return list;
  238. }
  239. /* find an element inside the list `list'. The current implementation calls the
  240. * CustomfindElement' passing a NULL reference as `func' */
  241. t_list * findElement(t_list *list, void *data)
  242. {
  243. t_list *current_elem;
  244. /* if the list is empty returns a NULL pointer */
  245. if (list == NULL)
  246. return NULL;
  247. /* intialize the value of `current_elem' */
  248. current_elem = list;
  249. while ( (current_elem != NULL)
  250. && ( LDATA(current_elem) != data) )
  251. {
  252. current_elem = LNEXT(current_elem);
  253. }
  254. /* postconditions */
  255. return current_elem;
  256. }
  257. /* find an element inside the list `list'. */
  258. t_list * CustomfindElement(t_list *list, void *data
  259. , int (*compareFunc)(void *a, void *b))
  260. {
  261. t_list *current_elem;
  262. /* preconditions */
  263. if (compareFunc == NULL)
  264. return findElement(list, data);
  265. if (list == NULL)
  266. return NULL;
  267. /* intialize the value of `current_elem' */
  268. current_elem = list;
  269. while (current_elem != NULL)
  270. {
  271. void *other_Data;
  272. other_Data = LDATA(current_elem);
  273. if (compareFunc(other_Data, data))
  274. break;
  275. current_elem = LNEXT(current_elem);
  276. }
  277. /* postconditions */
  278. return current_elem;
  279. }
  280. int getPosition(t_list *list, t_list *element)
  281. {
  282. int counter;
  283. /* preconditions */
  284. if (list == NULL || element == NULL)
  285. return -1;
  286. /* initialize the local variable `counter' */
  287. counter = 0;
  288. if (list == element)
  289. return counter;
  290. /* update values */
  291. counter++;
  292. list = LNEXT(list);
  293. while (list != NULL)
  294. {
  295. if (list == element)
  296. return counter;
  297. counter++;
  298. list = LNEXT(list);
  299. }
  300. return -1;
  301. }
  302. int getLength(t_list *list)
  303. {
  304. int counter;
  305. /* initialize the local variable `counter' */
  306. counter = 0;
  307. /* precondition */
  308. if (list == NULL)
  309. return counter;
  310. while (list != NULL)
  311. {
  312. counter++;
  313. list = LNEXT(list);
  314. }
  315. /* postconditions: return the length of the list */
  316. return counter;
  317. }
  318. t_list * cloneList(t_list *list)
  319. {
  320. t_list *result;
  321. t_list *current_element;
  322. /* initialize the local variables */
  323. result = NULL;
  324. current_element = list;
  325. /* preconditions */
  326. if (current_element == NULL)
  327. return result;
  328. while(current_element != NULL)
  329. {
  330. /* add an element to the new list */
  331. result = addElement(result, LDATA(current_element), -1);
  332. /* retrieve the next element of the list */
  333. current_element = LNEXT(current_element);
  334. }
  335. /* return the new list */
  336. return result;
  337. }
  338. t_list * getElementAt(t_list *list, unsigned int position)
  339. {
  340. t_list *result;
  341. t_list *current_element;
  342. unsigned int current_pos;
  343. if (list == NULL)
  344. return NULL;
  345. /* initialize the local variables */
  346. result = NULL;
  347. current_element = list;
  348. current_pos = 0;
  349. while((current_element != NULL) && (current_pos < position))
  350. {
  351. current_element = LNEXT(current_element);
  352. current_pos++;
  353. }
  354. /* return the element at the requested position */
  355. return current_element;
  356. }
  357. t_list * addList(t_list *list, t_list *elements)
  358. {
  359. t_list *current_element;
  360. void *current_data;
  361. /* if the list of elements is null, this function
  362. * will return `list' unmodified */
  363. if (elements == NULL)
  364. return list;
  365. /* initialize the value of `current_element' */
  366. current_element = elements;
  367. while (current_element != NULL)
  368. {
  369. /* retrieve the data associated with the current element */
  370. current_data = LDATA(current_element);
  371. list = addElement(list, current_data, -1);
  372. /* retrieve the next element in the list */
  373. current_element = LNEXT(current_element);
  374. }
  375. /* return the new list */
  376. return list;
  377. }
  378. t_list * addListToSet(t_list *list, t_list *elements
  379. , int (*compareFunc)(void *a, void *b), int *modified)
  380. {
  381. t_list *current_element;
  382. void *current_data;
  383. /* if the list of elements is NULL returns the current list */
  384. if (elements == NULL)
  385. return list;
  386. /* initialize the value of `current_element' */
  387. current_element = elements;
  388. while (current_element != NULL)
  389. {
  390. /* retrieve the data associated with the current element */
  391. current_data = LDATA(current_element);
  392. /* Test if the element was already inserted. */
  393. if (CustomfindElement(list, current_data, compareFunc) == NULL)
  394. {
  395. list = addElement(list, current_data, -1);
  396. if (modified != NULL)
  397. (* modified) = 1;
  398. }
  399. /* retrieve the next element in the list */
  400. current_element = LNEXT(current_element);
  401. }
  402. /* return the new list */
  403. return list;
  404. }
  405. /* add sorted */
  406. t_list * addSorted(t_list *list, void * data
  407. , int (*compareFunc)(void *a, void *b))
  408. {
  409. t_list *current_element;
  410. void *current_data;
  411. int counter;
  412. /* preconditions */
  413. if (list == NULL)
  414. return addFirst(list, data);
  415. counter = 0;
  416. current_element = list;
  417. while(current_element != NULL)
  418. {
  419. /* get the current interval informations */
  420. current_data = LDATA(current_element);
  421. assert(current_data != NULL);
  422. if (compareFunc(current_data, data) >= 0)
  423. {
  424. list = addElement(list, data, counter);
  425. return list;
  426. }
  427. /* retrieve the next element */
  428. current_element = LNEXT(current_element);
  429. /* update the value of counter */
  430. counter++;
  431. }
  432. return addElement(list, data, -1);
  433. }