pque.c 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. #include "pque.h"
  2. #include <stdlib.h>
  3. #include <string.h>
  4. void pq_init(PQue *pq, int cap, int elem_sz, int (*cmp)(void*, void*)) {
  5. pq->cap = cap;
  6. pq->size = 0;
  7. pq->elemsz = elem_sz;
  8. pq->cmp = cmp;
  9. pq->buf = malloc(cap * elem_sz);
  10. }
  11. static void swap(PQue *pq, int a, int b) {
  12. char buf[pq->elemsz];
  13. void *tmp = buf;
  14. int elemsz = pq->elemsz;
  15. memcpy(tmp, pq->buf + a*elemsz, elemsz);
  16. memcpy(pq->buf + a*elemsz, pq->buf + b*elemsz, elemsz);
  17. memcpy(pq->buf + b*elemsz, tmp, elemsz);
  18. }
  19. static int cmp(PQue *pq, int a, int b) {
  20. return pq->cmp(pq->buf + a*pq->elemsz, pq->buf + b*pq->elemsz);
  21. }
  22. void pq_push(PQue *pq, void *elem) {
  23. if (pq->size + 1 > pq->cap) {
  24. pq->buf = realloc(pq->buf, 2 * pq->cap * pq->elemsz);
  25. pq->cap *= 2;
  26. }
  27. memcpy(pq->buf + pq->size*pq->elemsz, elem, pq->elemsz);
  28. pq->size++;
  29. if (pq->size == 0) {
  30. return;
  31. }
  32. int i = pq->size - 1;
  33. while (i > 0 && cmp(pq, i, i/2) > 0) {
  34. swap(pq, i, i/2);
  35. i /= 2;
  36. }
  37. }
  38. static void heapify(PQue *pq, int idx) {
  39. int left, right, largest;
  40. left = 2 * idx +1;
  41. right = 2 * idx + 2;
  42. if (left < pq->size && cmp(pq, left, idx) > 0) {
  43. largest = left;
  44. } else {
  45. largest = idx;
  46. }
  47. if (right < pq->size && cmp(pq, right, largest) > 0) {
  48. largest = right;
  49. }
  50. if (largest != idx) {
  51. swap(pq, largest, idx);
  52. heapify(pq, largest);
  53. }
  54. }
  55. void pq_pop(PQue *pq) {
  56. if (pq->size == 0) return;
  57. memcpy(pq->buf, pq->buf+(pq->size - 1)*pq->elemsz, pq->elemsz);
  58. pq->size -= 1;
  59. heapify(pq, 0);
  60. }
  61. void* pq_top(PQue *pq) {
  62. if (pq->size == 0) return NULL;
  63. return pq->buf;
  64. }