summaryrefslogtreecommitdiffstats
path: root/src/dvec.c
diff options
context:
space:
mode:
authorLouis Burda <quent.burda@gmail.com>2023-05-26 04:02:39 +0200
committerLouis Burda <quent.burda@gmail.com>2023-05-26 04:02:39 +0200
commit046c59cd98066bc1fe9e48a27e048213ea80dede (patch)
treef149ad43acad9862fc83993ae80d3d0520d8b920 /src/dvec.c
parentf2542dd0d235474b6df46dcb7f5b4eafbccfde48 (diff)
downloadlibdvec-c-046c59cd98066bc1fe9e48a27e048213ea80dede.tar.gz
libdvec-c-046c59cd98066bc1fe9e48a27e048213ea80dede.zip
Add bubble sort and binary search
Diffstat (limited to 'src/dvec.c')
-rw-r--r--src/dvec.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/src/dvec.c b/src/dvec.c
index dac32b6..3ecef19 100644
--- a/src/dvec.c
+++ b/src/dvec.c
@@ -262,3 +262,74 @@ dvec_iter_bwd(const struct dvec *dvec, const void *p)
return NULL;
}
}
+
+int
+dvec_bubble_sort(struct dvec *dvec, bool reverse, dvec_sort_order_fn in_order)
+{
+ void *cur, *next, *tmp;
+ size_t i, k;
+ int rc;
+
+ rc = dvec_reserve(dvec, dvec->len + 1);
+ if (rc) return rc;
+
+ tmp = dvec->data + dvec->len * dvec->dsize;
+
+ for (i = 1; i < dvec->len; i++) {
+ cur = dvec->data;
+ for (k = 0; k < dvec->len - i; k++) {
+ next = cur + dvec->dsize;
+ if (in_order(cur, next) == !reverse) {
+ memcpy(tmp, cur, dvec->dsize);
+ memcpy(cur, next, dvec->dsize);
+ memcpy(next, tmp, dvec->dsize);
+ }
+ cur = next;
+ }
+ }
+
+ return 0;
+}
+
+ssize_t
+dvec_binary_search(struct dvec *dvec, dvec_search_cmp_fn search_cmp,
+ void *user, ssize_t *lower, ssize_t *higher)
+{
+ size_t min, max, pos;
+ int rc;
+
+ min = 0;
+ max = dvec->len;
+
+ if (lower) *lower = -1;
+ if (higher) *higher = -1;
+ while (min < max) {
+ pos = min + (max - min) / 2;
+ rc = search_cmp(dvec_at(dvec, pos), user);
+ if (!rc) {
+ if (lower && pos > 0)
+ *lower = (ssize_t) pos - 1;
+ if (higher && pos < dvec->len - 1)
+ *higher = (ssize_t) pos + 1;
+ return (ssize_t) pos;
+ } else if (rc > 0) {
+ if (pos + 1 == max) {
+ if (lower) *lower = (ssize_t) min;
+ if (higher && min < dvec->len - 1)
+ *higher = (ssize_t) min + 1;
+ break;
+ }
+ min = pos + 1;
+ } else {
+ if (min == pos) {
+ if (higher) *higher = (ssize_t) min;
+ if (lower && min > 0)
+ *lower = (ssize_t) min - 1;
+ break;
+ }
+ max = pos;
+ }
+ }
+
+ return -1;
+}