summaryrefslogtreecommitdiff
path: root/musl_heapsort.c
diff options
context:
space:
mode:
Diffstat (limited to 'musl_heapsort.c')
-rw-r--r--musl_heapsort.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/musl_heapsort.c b/musl_heapsort.c
new file mode 100644
index 0000000..33a72d5
--- /dev/null
+++ b/musl_heapsort.c
@@ -0,0 +1,37 @@
+#include <stdlib.h>
+
+#include "sorters.h"
+#include "common.h"
+
+/* A simple heap sort implementation.. only in-place O(nlogn) sort I know. */
+
+#define MIN(a, b) ((a)<(b) ? (a) : (b))
+
+static void sift(char *base, size_t root, size_t nel, size_t width, int (*cmp)(const void *, const void *))
+{
+ size_t max;
+
+ while (2*root <= nel) {
+ max = 2*root;
+ if (max < nel && cmp(base+max*width, base+(max+1)*width) < 0)
+ max++;
+ if (max && cmp(base+root*width, base+max*width) < 0) {
+ swap(base+root*width, base+max*width, width);
+ root = max;
+ } else break;
+ }
+}
+
+void musl_heapsort(void *_base, size_t nel, size_t width, cmpfun cmp)
+{
+ char *base = _base;
+ size_t i;
+
+ if (!nel) return;
+ for (i=(nel+1)/2; i; i--)
+ sift(base, i-1, nel-1, width, cmp);
+ for (i=nel-1; i; i--) {
+ swap(base, base+i*width, width);
+ sift(base, 0, i-1, width, cmp);
+ }
+}