Fix heapsort, add test

This commit is contained in:
Nils O. Selåsdal
2013-12-03 11:30:09 +01:00
parent a5662a2edd
commit 70fb352656
4 changed files with 130 additions and 16 deletions
+13 -4
View File
@@ -8,11 +8,20 @@ extern "C" {
#endif #endif
///compare function. Needs only to return < 0 if ///compare function. Needs only to return < 0 if
//the first element is less than the second //the first element is less than the second
typedef int (*uc_hs_cmp)(const void *, const void *); typedef int (*uc_hs_cmp)(const void *, const void *, void *cookie);
//swap function
typedef void (*uc_hs_swp)(void *, void *);
void /** Sort an array.
uc_heapsort(void *base, size_t count, size_t width, * @param base start of array
uc_hs_cmp cmp); * @param count number of elements in array
* @param width size of each element
* @param cmp compare function
* @param swap swap function
* @param cookie user pointer passed back to compare function
*/
void uc_heapsort(void *base, size_t count, size_t width,
uc_hs_cmp cmp, uc_hs_swp swap, void *cookie);
#ifdef __cplusplus #ifdef __cplusplus
} }
+14 -10
View File
@@ -3,39 +3,43 @@
static void static void
uc_sift(unsigned char *base, size_t start, size_t count, size_t width, uc_sift(unsigned char *base, size_t start, size_t count, size_t width,
uc_hs_cmp cmp) uc_hs_cmp cmp, uc_hs_swp swap, void *cookie)
{ {
size_t root = start, child; size_t root = start, child;
while ((root * 2 + 1) < count) { while ((root * 2 + 1) < count) {
child = root * 2 + 1; child = root * 2 + 1;
if (child < (count - 1) if (child < (count - 1)) {
&& cmp(&base[child * width], &base[(child + 1) * width]) < 0) int rc = cmp(&base[child * width], &base[(child + 1) * width], cookie);
if (rc < 0) {
child++; child++;
}
}
if (cmp(&base[root * width], &base[child * width]) < 0) { if (cmp(&base[root * width], &base[child * width], cookie) < 0) {
memcpy(base + root * width, base + child * width, width); swap(base + root * width, base + child * width);
root = child; root = child;
} else } else {
return; return;
} }
}
} }
void void
uc_heapsort(void *base_, size_t count, size_t width, uc_heapsort(void *base_, size_t count, size_t width,
uc_hs_cmp cmp) uc_hs_cmp cmp, uc_hs_swp swap, void *cookie)
{ {
int start = count / 2 - 1, end = count - 1; int start = count / 2 - 1, end = count - 1;
unsigned char *base = base_; unsigned char *base = base_;
while (start >= 0) { while (start >= 0) {
uc_sift(base, start, count, width, cmp); uc_sift(base, start, count, width, cmp, swap, cookie);
start--; start--;
} }
while (end > 0) { while (end > 0) {
memcpy(base + end * width, base, width); swap(base + end * width, base);
uc_sift(base, 0, end, width, cmp); uc_sift(base, 0, end, width, cmp, swap, cookie);
end--; end--;
} }
} }
+99
View File
@@ -0,0 +1,99 @@
#include <check.h>
#include <ucore/utils.h>
#include <ucore/heapsort.h>
struct Stuff {
char text[11];
int order;
};
static void swap_stuff(void *a_, void *b_)
{
struct Stuff *a = a_;
struct Stuff *b = b_;
struct Stuff tmp;
tmp = *a;
*a = *b;
*b = tmp;
}
static int cmp_stuff(const void *a_, const void *b_, void *cookie)
{
const struct Stuff *a = a_;
const struct Stuff *b = b_;
(void)cookie;
if (a->order < b->order)
return -1;
return 1;
}
void print_stuff(const struct Stuff *s, size_t len)
{
size_t i;
for(i = 0; i < len; i++) {
printf("%s:%d\n", s[i].text, s[i].order);
}
}
START_TEST (test_heapsort_odd)
struct Stuff unordered[] = {
{"2", 2},
{"1", 1},
{"4", 4},
{"5", 5},
{"3", 3},
};
struct Stuff ordered[] = {
{"1", 1},
{"2", 2},
{"3", 3},
{"4", 4},
{"5", 5},
};
uc_heapsort(unordered, ARRAY_SIZE(unordered), sizeof(struct Stuff),
cmp_stuff, swap_stuff, NULL);
//print_stuff(unordered, ARRAY_SIZE(unordered));
fail_if(memcmp(unordered, ordered, sizeof unordered) != 0);
END_TEST
START_TEST (test_heapsort_even)
struct Stuff unordered[] = {
{"1", 1},
{"7", 7},
{"3", 3},
{"4", 4},
{"6", 6},
{"2", 2},
};
struct Stuff ordered[] = {
{"1", 1},
{"2", 2},
{"3", 3},
{"4", 4},
{"6", 6},
{"7", 7},
};
uc_heapsort(unordered, ARRAY_SIZE(unordered), sizeof(struct Stuff),
cmp_stuff, swap_stuff, NULL);
print_stuff(unordered, ARRAY_SIZE(unordered));
fail_if(memcmp(unordered, ordered, sizeof unordered) != 0);
END_TEST
Suite *heapsort_suite(void)
{
Suite *s = suite_create("heapsort");
TCase *tc = tcase_create("heapsort tests");
tcase_add_test(tc, test_heapsort_odd);
tcase_add_test(tc, test_heapsort_even);
suite_add_tcase(s, tc);
return s;
}
+3 -1
View File
@@ -27,6 +27,7 @@ extern Suite *sprintb_suite(void);
extern Suite *strv_suite(void); extern Suite *strv_suite(void);
extern Suite *ratelimit_suite(void); extern Suite *ratelimit_suite(void);
extern Suite *htable_suite(void); extern Suite *htable_suite(void);
extern Suite *heapsort_suite(void);
static suite_func suites[] = { static suite_func suites[] = {
bitvec_suite, bitvec_suite,
@@ -48,7 +49,8 @@ static suite_func suites[] = {
ratelimit_suite, ratelimit_suite,
htable_suite, htable_suite,
clock_suite, clock_suite,
threadqueue_suite threadqueue_suite,
heapsort_suite
}; };
int int