mirror of
https://gitee.com/apaki/unicstl.git
synced 2026-05-28 22:54:19 +08:00
refactor(heap): 基于darray重构堆
This commit is contained in:
parent
81d9cf3c13
commit
18c67dacb3
25
README.md
25
README.md
@ -23,18 +23,18 @@ classDiagram
|
||||
direction TB
|
||||
|
||||
namespace basic {
|
||||
class ringbuf{
|
||||
不扩容或
|
||||
小数据扩容
|
||||
}
|
||||
class rawbuf
|
||||
class darray
|
||||
class linklist{
|
||||
<<单链表>>
|
||||
}
|
||||
class dlinklist{
|
||||
<<双向链表>>
|
||||
}
|
||||
class ringbuf{
|
||||
不扩容或
|
||||
小数据扩容
|
||||
}
|
||||
class rawbuf
|
||||
class darray
|
||||
}
|
||||
|
||||
namespace embed {
|
||||
@ -58,7 +58,6 @@ namespace hal {
|
||||
切片
|
||||
负索引
|
||||
}
|
||||
class string
|
||||
class hashtable
|
||||
}
|
||||
|
||||
@ -69,9 +68,13 @@ namespace adapter {
|
||||
namespace top {
|
||||
class stack
|
||||
class queue
|
||||
|
||||
class rbtree
|
||||
class map
|
||||
|
||||
class string
|
||||
class unordered_map
|
||||
class heap
|
||||
}
|
||||
|
||||
%% hal层
|
||||
@ -90,6 +93,7 @@ deque *-- segarray : 组合
|
||||
%% 通用标准容器
|
||||
stack *-- deque : 组合
|
||||
queue *-- deque : 组合
|
||||
heap *-- darray : 组合
|
||||
|
||||
%% 红黑树
|
||||
rbtree ..> stack : 依赖
|
||||
@ -108,14 +112,18 @@ equeue ..> ringbuf : 依赖
|
||||
|
||||
### 底层基础容器
|
||||
|
||||
#### 链表结构
|
||||
|数据结构 |名称 |说明 |
|
||||
|---|---|---|
|
||||
| linklist | 单链表 |
|
||||
| dlinklist | 双向链表 |
|
||||
|
||||
#### 数组结构
|
||||
|数据结构 |名称 |说明 |
|
||||
|---|---|---|
|
||||
| darray | 动态数组 | 扩容
|
||||
| ringbuf | 环形缓存区 | 扩容/外部缓存
|
||||
| rawbuf | 原始缓冲区 | 动态分配固定容量/外部缓存
|
||||
| segarray | 分段数组 | 扩容
|
||||
|
||||
### 中层容器
|
||||
|数据结构 |名称 |说明 |
|
||||
@ -136,6 +144,7 @@ equeue ..> ringbuf : 依赖
|
||||
| stack | 栈 | 扩容
|
||||
| queue | 队列 | 扩容
|
||||
| ustring | 字符串 | 扩容
|
||||
| heap | 堆 | 扩容
|
||||
|
||||
### 嵌入式专用容器
|
||||
> 适配嵌入式场景、外置内存、无动态堆分配
|
||||
|
||||
@ -20,7 +20,7 @@ void demo_heap_num(void)
|
||||
int temp = 0;
|
||||
size_t len = sizeof(data) / sizeof(data[0]);
|
||||
|
||||
heap_t heap = heap_min_new2(sizeof(int), 64);
|
||||
heap_t heap = heap_min_new(sizeof(int), 64);
|
||||
heap->print_obj = print_num;
|
||||
heap->compare = compare_num;
|
||||
|
||||
@ -86,7 +86,7 @@ static void demo_heap_struct(void)
|
||||
struct _student temp = {0};
|
||||
size_t len = sizeof(data) / sizeof(data[0]);
|
||||
|
||||
heap_t heap = heap_min_new2(sizeof(struct _student), 64);
|
||||
heap_t heap = heap_min_new(sizeof(struct _student), 64);
|
||||
heap->print_obj = print_struct;
|
||||
heap->compare = compare_struct;
|
||||
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
#define _HEAP_H_
|
||||
|
||||
#include "unicstl_internal.h"
|
||||
#include "darray.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
@ -22,12 +23,7 @@ typedef enum
|
||||
struct _heap
|
||||
{
|
||||
// -------------------- private --------------------
|
||||
void* obj;
|
||||
|
||||
size_t _size;
|
||||
size_t _obj_size;
|
||||
size_t _capacity;
|
||||
size_t _ratio;
|
||||
darray_t _darray;
|
||||
|
||||
heap_type _type;
|
||||
struct _iterator _iter;
|
||||
@ -41,8 +37,10 @@ struct _heap
|
||||
bool (*peek)(struct _heap* self, void* obj);
|
||||
|
||||
// base
|
||||
bool (*empty)(struct _heap* self);
|
||||
bool (*reserve)(struct _heap* self, size_t capacity);
|
||||
size_t (*capacity)(struct _heap* self);
|
||||
size_t (*size)(struct _heap* self);
|
||||
bool (*empty)(struct _heap* self);
|
||||
bool (*clear)(struct _heap* self);
|
||||
|
||||
// iter
|
||||
@ -58,8 +56,8 @@ struct _heap
|
||||
typedef struct _heap* heap_t;
|
||||
|
||||
// create and free heap
|
||||
heap_t heap_max_new2(size_t obj_size, size_t capacity);
|
||||
heap_t heap_min_new2(size_t obj_size, size_t capacity);
|
||||
heap_t heap_max_new(size_t obj_size, size_t capacity);
|
||||
heap_t heap_min_new(size_t obj_size, size_t capacity);
|
||||
|
||||
void heap_free(heap_t* heap);
|
||||
|
||||
|
||||
@ -147,6 +147,34 @@ static inline void *unicstl_realloc(void *ptr, size_t size) { return NULL; }
|
||||
static inline void unicstl_free(void *ptr) {}
|
||||
#endif // UNICSTL_MALLOC_ENABLE
|
||||
|
||||
|
||||
/**
|
||||
* @brief obj compare with obj2
|
||||
*
|
||||
* @return
|
||||
* obj < obj2 return -1
|
||||
* obj == obj2 return 0
|
||||
* obj > obj2 return 1
|
||||
*/
|
||||
typedef int (*compare_fun_t)(const void *obj, const void *obj2);
|
||||
|
||||
|
||||
|
||||
static inline size_t ring_index(size_t head, size_t index, size_t capacity)
|
||||
{
|
||||
return (head + index) % capacity;
|
||||
}
|
||||
|
||||
static inline size_t ring_index_next(size_t index, size_t capacity)
|
||||
{
|
||||
return (index + 1) % capacity;
|
||||
}
|
||||
|
||||
static inline size_t ring_index_prev(size_t index, size_t capacity)
|
||||
{
|
||||
return index == 0 ? (capacity - 1) : index - 1;
|
||||
}
|
||||
|
||||
static inline const void *obj_at(const void *objs, size_t index, size_t obj_size)
|
||||
{
|
||||
unicstl_assert(objs != NULL);
|
||||
@ -191,32 +219,27 @@ static inline void obj_zero(const void *objs, size_t index, size_t count, size_t
|
||||
memset((char *)objs + index * obj_size, 0, count * obj_size);
|
||||
}
|
||||
|
||||
|
||||
static inline size_t ring_index(size_t head, size_t index, size_t capacity)
|
||||
static inline void mem_swap(const void *obj1, void *obj2, size_t obj_size)
|
||||
{
|
||||
return (head + index) % capacity;
|
||||
size_t cnt = obj_size;
|
||||
for(size_t i = 0; i < cnt; ++i)
|
||||
{
|
||||
char tmp = ((char*)obj1)[i];
|
||||
((char*)obj1)[i] = ((char*)obj2)[i];
|
||||
((char*)obj2)[i] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
static inline size_t ring_index_next(size_t index, size_t capacity)
|
||||
static inline void obj_swap(const void *base, size_t index1, size_t index2, size_t obj_size)
|
||||
{
|
||||
return (index + 1) % capacity;
|
||||
mem_swap((char*)base + index1 * obj_size, (char*)base + index2 * obj_size, obj_size);
|
||||
}
|
||||
|
||||
static inline size_t ring_index_prev(size_t index, size_t capacity)
|
||||
static inline int compare_obj(const void *base, size_t index1, size_t index2, size_t obj_size, compare_fun_t cmp)
|
||||
{
|
||||
return index == 0 ? (capacity - 1) : index - 1;
|
||||
return cmp((char*)base + index1 * obj_size, (char*)base + index2 * obj_size);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief obj compare with obj2
|
||||
*
|
||||
* @return
|
||||
* obj < obj2 return -1
|
||||
* obj == obj2 return 0
|
||||
* obj > obj2 return 1
|
||||
*/
|
||||
typedef int (*compare_fun_t)(const void *obj, const void *obj2);
|
||||
|
||||
// default function
|
||||
int default_compare(const void *obj1, const void *obj2);
|
||||
void default_print_obj(const void *obj);
|
||||
|
||||
21
src/algo.c
21
src/algo.c
@ -10,27 +10,6 @@
|
||||
*/
|
||||
#include "algo.h"
|
||||
|
||||
static inline void mem_swap(const void *obj1, void *obj2, size_t obj_size)
|
||||
{
|
||||
size_t cnt = obj_size;
|
||||
for(size_t i = 0; i < cnt; ++i)
|
||||
{
|
||||
char tmp = ((char*)obj1)[i];
|
||||
((char*)obj1)[i] = ((char*)obj2)[i];
|
||||
((char*)obj2)[i] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void obj_swap(const void *base, size_t index1, size_t index2, size_t obj_size)
|
||||
{
|
||||
mem_swap((char*)base + index1 * obj_size, (char*)base + index2 * obj_size, obj_size);
|
||||
}
|
||||
|
||||
static inline int compare_obj(const void *base, size_t index1, size_t index2, size_t obj_size, compare_fun_t cmp)
|
||||
{
|
||||
return cmp((char*)base + index1 * obj_size, (char*)base + index2 * obj_size);
|
||||
}
|
||||
|
||||
// 1. 冒泡排序
|
||||
bool bubble_sort(void* base, size_t count, size_t obj_size, compare_fun_t cmp)
|
||||
{
|
||||
|
||||
199
src/heap.c
199
src/heap.c
@ -8,17 +8,17 @@
|
||||
*/
|
||||
#include "heap.h"
|
||||
|
||||
static int left(int i)
|
||||
static size_t left(size_t i)
|
||||
{
|
||||
return 2 * i + 1;
|
||||
}
|
||||
|
||||
static int right(int i)
|
||||
static size_t right(size_t i)
|
||||
{
|
||||
return (i << 1) + 2;
|
||||
}
|
||||
|
||||
static int parent(int i)
|
||||
static size_t parent(size_t i)
|
||||
{
|
||||
if(i == 0)
|
||||
{
|
||||
@ -30,56 +30,23 @@ static int parent(int i)
|
||||
static bool heap_peek(struct _heap* self, void* obj)
|
||||
{
|
||||
unicstl_assert(self != NULL);
|
||||
unicstl_assert(obj != NULL);
|
||||
if(obj == NULL)
|
||||
size_t index = self->size(self) - 1;
|
||||
if(!self->_darray->get(self->_darray, 0, obj))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(self->empty(self))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
memmove(obj, self->obj, self->_obj_size);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void heap_swap(struct _heap* self, int i, int j)
|
||||
{
|
||||
unicstl_assert(self != NULL);
|
||||
unicstl_assert(self->_obj_size != 0);
|
||||
#if __STDC_VERSION__ >= 199901L
|
||||
// #define C99_VLA // VLA should be avoided for portability reasons and due to the risk of stack overflow.
|
||||
#endif
|
||||
|
||||
#ifdef C99_VLA
|
||||
char tmp[self->_obj_size];
|
||||
#else
|
||||
char* tmp = unicstl_malloc(self->_obj_size);
|
||||
if (tmp == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
memmove(tmp, (char *)self->obj + i * self->_obj_size, self->_obj_size);
|
||||
memmove((char*)self->obj + i * self->_obj_size, (char*)self->obj + j * self->_obj_size, self->_obj_size);
|
||||
memmove((char*)self->obj + j * self->_obj_size, tmp, self->_obj_size);
|
||||
|
||||
#ifndef C99_VLA
|
||||
unicstl_free(tmp);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void heap_fixed_up(struct _heap* self, int i)
|
||||
static void heap_fixed_up(struct _heap* self, size_t i)
|
||||
{
|
||||
unicstl_assert(self != NULL);
|
||||
unicstl_assert(self->_darray != NULL);
|
||||
unicstl_assert(self->compare != NULL);
|
||||
int p = 0;
|
||||
|
||||
if(self->compare == NULL)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
const void *base = self->_darray->at(self->_darray, 0);
|
||||
size_t obj_size = self->_darray->_obj_size;
|
||||
size_t p = 0;
|
||||
|
||||
if(self->_type == HEAP_MAX)
|
||||
{
|
||||
@ -87,12 +54,14 @@ static void heap_fixed_up(struct _heap* self, int i)
|
||||
{
|
||||
p = parent(i);
|
||||
// if current node is greater than its parent, swap the position. otherwise break out of loop
|
||||
if(p < 0 || self->compare((char *)self->obj + i * self->_obj_size, (char *)self->obj + p * self->_obj_size) <= 0)
|
||||
if(p == (size_t)-1 || compare_obj(base, i, p, obj_size, self->compare) <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
heap_swap(self, i, p);
|
||||
obj_swap(base, i, p, obj_size);
|
||||
i = p;
|
||||
|
||||
self->print(self);
|
||||
}
|
||||
}
|
||||
else /* if(self->_type == HEAP_MIN) */
|
||||
@ -100,13 +69,17 @@ static void heap_fixed_up(struct _heap* self, int i)
|
||||
while(1)
|
||||
{
|
||||
p = parent(i);
|
||||
log_debug("heap_fixed_up: p = %d, i = %zu\n", (ssize_t)p, i);
|
||||
|
||||
// if current node is less than its parent, swap the position. otherwise break out of loop
|
||||
if(p < 0 || self->compare((char *)self->obj + i * self->_obj_size, (char *)self->obj + p * self->_obj_size) >= 0)
|
||||
if(p == (size_t)-1 || compare_obj(base, i, p, obj_size, self->compare) >= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
heap_swap(self, i, p);
|
||||
obj_swap(base, i, p, obj_size);
|
||||
i = p;
|
||||
|
||||
self->print(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -114,28 +87,24 @@ static void heap_fixed_up(struct _heap* self, int i)
|
||||
static bool heap_push(struct _heap* self, void* obj)
|
||||
{
|
||||
unicstl_assert(self != NULL);
|
||||
if(self->size(self) > self->_capacity)
|
||||
unicstl_assert(self->_darray != NULL);
|
||||
if(!self->_darray->append(self->_darray, obj))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
size_t index = self->size(self);
|
||||
memmove((char *)self->obj + index * self->_obj_size, obj, self->_obj_size);
|
||||
self->_size++;
|
||||
|
||||
heap_fixed_up(self, index);
|
||||
heap_fixed_up(self, self->size(self) - 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void heap_fixed_down(struct _heap* self, int i)
|
||||
static void heap_fixed_down(struct _heap* self, size_t i)
|
||||
{
|
||||
unicstl_assert(self != NULL);
|
||||
int l = 0,r = 0;
|
||||
int max = 0, min = 0;
|
||||
unicstl_assert(self->_darray != NULL);
|
||||
size_t l = 0,r = 0;
|
||||
size_t max = 0, min = 0;
|
||||
|
||||
if(self->compare == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
const void *base = self->_darray->at(self->_darray, 0);
|
||||
size_t obj_size = self->_darray->_obj_size;
|
||||
|
||||
if(self->_type == HEAP_MAX)
|
||||
{
|
||||
@ -145,20 +114,20 @@ static void heap_fixed_down(struct _heap* self, int i)
|
||||
r = right(i);
|
||||
max = i;
|
||||
|
||||
if(l < self->size(self) && self->compare((char *)self->obj + l * self->_obj_size, (char *)self->obj + max * self->_obj_size) > 0)
|
||||
if(l < self->size(self) && compare_obj(base, l, max, obj_size, self->compare) > 0)
|
||||
{
|
||||
max = l;
|
||||
}
|
||||
|
||||
if(r < self->size(self) && self->compare((char *)self->obj + r * self->_obj_size, (char *)self->obj + max * self->_obj_size) > 0)
|
||||
if(r < self->size(self) && compare_obj(base, r, max, obj_size, self->compare) > 0)
|
||||
{
|
||||
max = r;
|
||||
}
|
||||
|
||||
if(max == i)
|
||||
{
|
||||
break;
|
||||
}
|
||||
heap_swap(self, i, max);
|
||||
obj_swap(base, i, max, obj_size);
|
||||
i = max;
|
||||
}
|
||||
}
|
||||
@ -170,12 +139,12 @@ static void heap_fixed_down(struct _heap* self, int i)
|
||||
r = right(i);
|
||||
min = i;
|
||||
|
||||
if(l < self->size(self) && self->compare((char *)self->obj + l * self->_obj_size, (char *)self->obj + min * self->_obj_size) < 0)
|
||||
if(l < self->size(self) && compare_obj(base, l, min, obj_size, self->compare) < 0)
|
||||
{
|
||||
min = l;
|
||||
}
|
||||
|
||||
if(r < self->size(self) && self->compare((char *)self->obj + r * self->_obj_size, (char *)self->obj + min * self->_obj_size) < 0)
|
||||
if(r < self->size(self) && compare_obj(base, r, min, obj_size, self->compare) < 0)
|
||||
{
|
||||
min = r;
|
||||
}
|
||||
@ -183,7 +152,7 @@ static void heap_fixed_down(struct _heap* self, int i)
|
||||
{
|
||||
break;
|
||||
}
|
||||
heap_swap(self, i, min);
|
||||
obj_swap(self, i, min, obj_size);
|
||||
i = min;
|
||||
}
|
||||
}
|
||||
@ -192,25 +161,34 @@ static void heap_fixed_down(struct _heap* self, int i)
|
||||
static bool heap_pop(struct _heap* self, void* obj)
|
||||
{
|
||||
unicstl_assert(self != NULL);
|
||||
if(self->empty(self))
|
||||
unicstl_assert(self->_darray != NULL);
|
||||
if(!self->_darray->pop(self->_darray, obj))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int index = self->size(self) - 1;
|
||||
heap_swap(self, 0, index);
|
||||
if(obj != NULL)
|
||||
{
|
||||
memmove(obj, (char *)self->obj + index * self->_obj_size, self->_obj_size);
|
||||
}
|
||||
self->_size--;
|
||||
heap_fixed_down(self, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
static size_t heap_reserve(struct _heap* self, size_t capacity)
|
||||
{
|
||||
unicstl_assert(self != NULL);
|
||||
unicstl_assert(self->_darray != NULL);
|
||||
return self->_darray->reserve(self->_darray, capacity);
|
||||
}
|
||||
|
||||
static size_t heap_size(struct _heap* self)
|
||||
{
|
||||
unicstl_assert(self != NULL);
|
||||
return self->_size;
|
||||
unicstl_assert(self->_darray != NULL);
|
||||
return self->_darray->size(self->_darray);
|
||||
}
|
||||
|
||||
static size_t heap_capacity(struct _heap* self)
|
||||
{
|
||||
unicstl_assert(self != NULL);
|
||||
unicstl_assert(self->_darray != NULL);
|
||||
return self->_darray->capacity(self->_darray);
|
||||
}
|
||||
|
||||
static bool heap_empty(struct _heap* self)
|
||||
@ -222,34 +200,26 @@ static bool heap_empty(struct _heap* self)
|
||||
static bool heap_clear(struct _heap* self)
|
||||
{
|
||||
unicstl_assert(self != NULL);
|
||||
self->_size = 0;
|
||||
return true;
|
||||
unicstl_assert(self->_darray != NULL);
|
||||
return self->_darray->clear(self->_darray);
|
||||
}
|
||||
|
||||
static void heap_destory(struct _heap* self)
|
||||
{
|
||||
unicstl_assert(self != NULL);
|
||||
self->clear(self);
|
||||
if(self->obj)
|
||||
if(self->_darray != NULL)
|
||||
{
|
||||
unicstl_free(self->obj);
|
||||
darray_free(&self->_darray);
|
||||
}
|
||||
}
|
||||
|
||||
static void heap_print(struct _heap* self)
|
||||
{
|
||||
unicstl_assert(self != NULL);
|
||||
unicstl_assert(self->obj != NULL);
|
||||
|
||||
void* obj = NULL;
|
||||
size_t offset = 0;
|
||||
|
||||
for (int i = 0; i < self->size(self); i++)
|
||||
{
|
||||
offset = self->_obj_size * i;
|
||||
obj = (char *)self->obj + offset;
|
||||
self->print_obj(obj);
|
||||
}
|
||||
unicstl_assert(self->_darray != NULL);
|
||||
self->_darray->print_obj = self->print_obj;
|
||||
self->_darray->print(self->_darray);
|
||||
}
|
||||
|
||||
bool heap_iter_hasnext(struct _iterator* iter)
|
||||
@ -269,15 +239,12 @@ const void* heap_iter_next(struct _iterator* iter)
|
||||
{
|
||||
unicstl_assert(iter != NULL);
|
||||
unicstl_assert(iter->_container != NULL);
|
||||
|
||||
heap_t self = (heap_t)iter->_container;
|
||||
void *obj = NULL;
|
||||
unicstl_assert(self->_darray != NULL);
|
||||
|
||||
size_t index = iter->_index;
|
||||
obj = self->obj + self->_obj_size * index;
|
||||
|
||||
iter->_index += 1;
|
||||
return obj;
|
||||
return self->_darray->at(self->_darray, index);
|
||||
}
|
||||
|
||||
iterator_t heap_iter(struct _heap* self)
|
||||
@ -287,28 +254,20 @@ iterator_t heap_iter(struct _heap* self)
|
||||
|
||||
iter->_container = self;
|
||||
iter->_index = 0;
|
||||
iter->_node = self->obj;
|
||||
|
||||
iter->hasnext = heap_iter_hasnext;
|
||||
iter->next = heap_iter_next;
|
||||
return iter;
|
||||
}
|
||||
|
||||
static bool heap_init2(struct _heap* self, size_t obj_size, size_t capacity)
|
||||
static bool heap_init(struct _heap* self, size_t obj_size, size_t capacity, heap_type type)
|
||||
{
|
||||
unicstl_assert(self != NULL);
|
||||
unicstl_assert(obj_size > 0);
|
||||
|
||||
// -------------------- private --------------------
|
||||
self->_obj_size = obj_size;
|
||||
self->_size = 0;
|
||||
self->_capacity = capacity;
|
||||
self->_ratio = 2;
|
||||
|
||||
self->obj = (void*)unicstl_malloc(self->_capacity * self->_obj_size);
|
||||
if(self->obj == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
self->_darray = NULL;
|
||||
self->_type = type;
|
||||
|
||||
self->_destory = heap_destory;
|
||||
|
||||
@ -320,25 +279,31 @@ static bool heap_init2(struct _heap* self, size_t obj_size, size_t capacity)
|
||||
self->empty = heap_empty;
|
||||
|
||||
// base
|
||||
self->reserve = heap_reserve;
|
||||
self->capacity = heap_capacity;
|
||||
self->size = heap_size;
|
||||
self->clear = heap_clear;
|
||||
|
||||
// iter
|
||||
self->iter = heap_iter;
|
||||
|
||||
// config
|
||||
self->compare = NULL;
|
||||
|
||||
// -------------------- default --------------------
|
||||
self->compare = default_compare;
|
||||
self->print_obj = default_print_obj;
|
||||
|
||||
// -------------------- debug --------------------
|
||||
self->print = heap_print;
|
||||
|
||||
// -------------------- init --------------------
|
||||
self->_darray = darray_new(obj_size, capacity);
|
||||
if(self->_darray == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
heap_t heap_max_new2(size_t obj_size, size_t capacity)
|
||||
heap_t heap_max_new(size_t obj_size, size_t capacity)
|
||||
{
|
||||
heap_t heap = NULL;
|
||||
heap = (struct _heap*)unicstl_malloc(sizeof(struct _heap));
|
||||
@ -347,17 +312,15 @@ heap_t heap_max_new2(size_t obj_size, size_t capacity)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(heap_init2(heap, obj_size, capacity) != true)
|
||||
if(heap_init(heap, obj_size, capacity, HEAP_MAX) != true)
|
||||
{
|
||||
unicstl_free(heap);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
heap->_type = HEAP_MAX;
|
||||
return heap;
|
||||
}
|
||||
|
||||
heap_t heap_min_new2(size_t obj_size, size_t capacity)
|
||||
heap_t heap_min_new(size_t obj_size, size_t capacity)
|
||||
{
|
||||
heap_t heap = NULL;
|
||||
heap = (struct _heap*)unicstl_malloc(sizeof(struct _heap));
|
||||
@ -367,14 +330,12 @@ heap_t heap_min_new2(size_t obj_size, size_t capacity)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(heap_init2(heap, obj_size, capacity) != true)
|
||||
if(heap_init(heap, obj_size, capacity, HEAP_MIN) != true)
|
||||
{
|
||||
log_warn("heap init failed\n");
|
||||
unicstl_free(heap);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
heap->_type = HEAP_MIN;
|
||||
return heap;
|
||||
}
|
||||
|
||||
|
||||
@ -10,27 +10,39 @@
|
||||
*/
|
||||
#include "test.h"
|
||||
|
||||
static void* get_max(struct _heap* heap, void *array, int start, int end)
|
||||
static const void* get_max(const void *base, size_t index, size_t count, size_t obj_size, compare_fun_t compare)
|
||||
{
|
||||
void* max = array;
|
||||
for (int i = start; i < end; i++)
|
||||
const void* max = base;
|
||||
if(count <= 1)
|
||||
{
|
||||
if (heap->compare((char*)array + heap->_obj_size * i, max) > 0)
|
||||
return base;
|
||||
}
|
||||
size_t idx = 0;
|
||||
for (size_t i = 0; i < count; i++)
|
||||
{
|
||||
max = (char*)array + heap->_obj_size * i;
|
||||
idx = index + i * obj_size;
|
||||
if (compare((char*)base + idx, max) > 0)
|
||||
{
|
||||
max = (char*)base + idx;
|
||||
}
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
static void* get_min(struct _heap* heap, void *array, int start, int end)
|
||||
static const void* get_min(const void *base, size_t index, size_t count, size_t obj_size, compare_fun_t compare)
|
||||
{
|
||||
void* min = array;
|
||||
for (int i = start; i < end; i++)
|
||||
const void* min = base;
|
||||
if(count <= 1)
|
||||
{
|
||||
if (heap->compare((char*)array + heap->_obj_size * i, min) < 0)
|
||||
return base;
|
||||
}
|
||||
size_t idx = 0;
|
||||
for (size_t i = 0; i < count ; i++)
|
||||
{
|
||||
min = (char*)array + heap->_obj_size * i;
|
||||
idx = index + i * obj_size;
|
||||
if (compare((char*)base + idx, min) < 0)
|
||||
{
|
||||
min = (char*)base + idx;
|
||||
}
|
||||
}
|
||||
return min;
|
||||
@ -45,8 +57,9 @@ static void test_heap_min_num(void)
|
||||
int data[] = { 5,2,3,1,7,8,6,4,9,10,12,11,15,14,13 };
|
||||
int temp = 0;
|
||||
size_t len = sizeof(data) / sizeof(data[0]);
|
||||
int min = 0;
|
||||
|
||||
heap_t heap = heap_min_new2(sizeof(int), 64);
|
||||
heap_t heap = heap_min_new(sizeof(int), 64);
|
||||
TEST_ASSERT_NOT_NULL(heap);
|
||||
heap->print_obj = print_num;
|
||||
heap->compare = compare_num;
|
||||
@ -58,7 +71,9 @@ static void test_heap_min_num(void)
|
||||
TEST_ASSERT_EQUAL_INT(i + 1, heap->size(heap));
|
||||
|
||||
TEST_ASSERT_TRUE(heap->peek(heap, &temp));
|
||||
TEST_ASSERT_EQUAL_INT(*(int *)get_min(heap, data, 0, heap->size(heap)), temp);
|
||||
min = *(int *)get_min(data, 0, i + 1, sizeof(int), compare_num);
|
||||
log_debug("i = %d, min = %d, heap_peek: %d, ", i, min, temp);
|
||||
TEST_ASSERT_EQUAL_INT(min, temp);
|
||||
}
|
||||
|
||||
TEST_ASSERT_TRUE(heap->clear(heap));
|
||||
@ -96,7 +111,7 @@ static void test_heap_min_struct(void)
|
||||
struct _student temp = {0};
|
||||
size_t len = sizeof(data) / sizeof(data[0]);
|
||||
|
||||
heap_t heap = heap_min_new2(sizeof(struct _student), 64);
|
||||
heap_t heap = heap_min_new(sizeof(struct _student), 64);
|
||||
TEST_ASSERT_NOT_NULL(heap);
|
||||
heap->print_obj = print_struct;
|
||||
heap->compare = compare_struct;
|
||||
@ -108,8 +123,8 @@ static void test_heap_min_struct(void)
|
||||
TEST_ASSERT_EQUAL_INT(i + 1, heap->size(heap));
|
||||
|
||||
TEST_ASSERT_TRUE(heap->peek(heap, &temp));
|
||||
TEST_ASSERT_EQUAL_INT(((struct _student*)get_min(heap, data, 0, heap->size(heap)))->id, temp.id);
|
||||
TEST_ASSERT_EQUAL_STRING(((struct _student*)get_min(heap, data, 0, heap->size(heap)))->name, temp.name);
|
||||
TEST_ASSERT_EQUAL_INT(((struct _student*)get_min(data, 0, i + 1, sizeof(struct _student), compare_struct))->id, temp.id);
|
||||
TEST_ASSERT_EQUAL_STRING(((struct _student*)get_min(data, 0, i + 1, sizeof(struct _student), compare_struct))->name, temp.name);
|
||||
}
|
||||
TEST_ASSERT_TRUE(heap->peek(heap, &temp));
|
||||
TEST_ASSERT_TRUE(heap->peek(heap, &temp));
|
||||
@ -143,7 +158,7 @@ static void test_heap_max_num(void)
|
||||
int temp = 0;
|
||||
size_t len = sizeof(data) / sizeof(data[0]);
|
||||
|
||||
heap_t heap = heap_max_new2(sizeof(int), 64);
|
||||
heap_t heap = heap_max_new(sizeof(int), 64);
|
||||
TEST_ASSERT_NOT_NULL(heap);
|
||||
heap->print_obj = print_num;
|
||||
heap->compare = compare_num;
|
||||
@ -155,7 +170,7 @@ static void test_heap_max_num(void)
|
||||
TEST_ASSERT_EQUAL_INT(i + 1, heap->size(heap));
|
||||
|
||||
TEST_ASSERT_TRUE(heap->peek(heap, &temp));
|
||||
TEST_ASSERT_EQUAL_INT(*(int *)get_max(heap, data, 0, heap->size(heap)), temp);
|
||||
TEST_ASSERT_EQUAL_INT(*(int *)get_max(data, 0, i + 1, sizeof(int), compare_num), temp);
|
||||
}
|
||||
|
||||
TEST_ASSERT_TRUE(heap->clear(heap));
|
||||
@ -193,7 +208,7 @@ static void test_heap_max_struct(void)
|
||||
struct _student temp = {0};
|
||||
size_t len = sizeof(data) / sizeof(data[0]);
|
||||
|
||||
heap_t heap = heap_max_new2(sizeof(struct _student), 64);
|
||||
heap_t heap = heap_max_new(sizeof(struct _student), 64);
|
||||
TEST_ASSERT_NOT_NULL(heap);
|
||||
heap->print_obj = print_struct;
|
||||
heap->compare = compare_struct;
|
||||
@ -205,8 +220,8 @@ static void test_heap_max_struct(void)
|
||||
TEST_ASSERT_EQUAL_INT(i + 1, heap->size(heap));
|
||||
|
||||
TEST_ASSERT_TRUE(heap->peek(heap, &temp));
|
||||
TEST_ASSERT_EQUAL_INT(((struct _student*)get_max(heap, data, 0, heap->size(heap)))->id, temp.id);
|
||||
TEST_ASSERT_EQUAL_STRING(((struct _student*)get_max(heap, data, 0, heap->size(heap)))->name, temp.name);
|
||||
TEST_ASSERT_EQUAL_INT(((struct _student*)get_max(data, 0, i + 1, sizeof(struct _student), compare_struct))->id, temp.id);
|
||||
TEST_ASSERT_EQUAL_STRING(((struct _student*)get_max(data, 0, i + 1, sizeof(struct _student), compare_struct))->name, temp.name);
|
||||
|
||||
// heap->print_obj(&temp);
|
||||
// printf("\n");
|
||||
@ -260,7 +275,7 @@ static void test_heap_max_iter(void)
|
||||
int out[15] = { 0 };
|
||||
int outlen = 0;
|
||||
|
||||
heap_t heap = heap_max_new2(sizeof(int), 64);
|
||||
heap_t heap = heap_max_new(sizeof(int), 64);
|
||||
TEST_ASSERT_NOT_NULL(heap);
|
||||
heap->print_obj = print_num;
|
||||
heap->compare = compare_num;
|
||||
@ -272,7 +287,7 @@ static void test_heap_max_iter(void)
|
||||
TEST_ASSERT_EQUAL_INT(i + 1, heap->size(heap));
|
||||
|
||||
TEST_ASSERT_TRUE(heap->peek(heap, &temp));
|
||||
TEST_ASSERT_EQUAL_INT(*(int *)get_max(heap, data, 0, heap->size(heap)), temp);
|
||||
TEST_ASSERT_EQUAL_INT(*(int *)get_max(data, 0, i + 1, sizeof(int), compare_num), temp);
|
||||
|
||||
iterator_t iter = heap->iter(heap);
|
||||
|
||||
|
||||
@ -512,7 +512,7 @@ static void test_ringbuf_iter(void)
|
||||
TEST_ASSERT_EQUAL_INT(data[i], temp);
|
||||
i--;
|
||||
|
||||
ringbuf->print_obj(&temp);
|
||||
// ringbuf->print_obj(&temp);
|
||||
}
|
||||
TEST_ASSERT_EQUAL_INT(-1, i);
|
||||
|
||||
|
||||
@ -33,10 +33,22 @@ void test_unicstl_capacity(void)
|
||||
TEST_ASSERT_EQUAL_UINT32(1125000, unicstl_new_capacity(1000000));
|
||||
}
|
||||
|
||||
void test_unicstl_compare_obj(void)
|
||||
{
|
||||
int data[] = {1,2,3};
|
||||
int obj_size = sizeof(int);
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(0, compare_obj(data, 0, 0, obj_size, compare_int));
|
||||
TEST_ASSERT_EQUAL_INT(1, compare_obj(data, 2, 1, obj_size, compare_int));
|
||||
TEST_ASSERT_EQUAL_INT(-1, compare_obj(data, 0, 1, obj_size, compare_int));
|
||||
}
|
||||
|
||||
void test_unicstl(void)
|
||||
{
|
||||
UnitySetTestFile(__FILE__);
|
||||
|
||||
RUN_TEST(test_unicstl_version);
|
||||
RUN_TEST(test_unicstl_capacity);
|
||||
|
||||
RUN_TEST(test_unicstl_compare_obj);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user