Fix heapsort, add test
This commit is contained in:
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-11
@@ -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);
|
||||||
child++;
|
if (rc < 0) {
|
||||||
|
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--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user