mirror of
https://gitee.com/apaki/unicstl.git
synced 2026-05-28 22:54:19 +08:00
feat(algo): 新增算法模块并给darray集成排序和查找功能,index底层改为调用search
This commit is contained in:
parent
f8ba5197a8
commit
d36346ce00
78
include/algo.h
Normal file
78
include/algo.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/**
|
||||||
|
* @file algo.h
|
||||||
|
* @author wenjf (Orig5826@163.com)
|
||||||
|
* @brief
|
||||||
|
* @version 0.1
|
||||||
|
* @date 2026-05-14
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2026
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef _ALGO_H_
|
||||||
|
#define _ALGO_H_
|
||||||
|
|
||||||
|
#include "unicstl_internal.h"
|
||||||
|
|
||||||
|
static inline void obj_swap(const void *base, size_t index, void *obj, size_t obj_size)
|
||||||
|
{
|
||||||
|
//...
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// --------------------------------------------------
|
||||||
|
// 排序算法
|
||||||
|
// void __cdecl qsort(void *_Base,size_t _NumOfElements,size_t _SizeOfElements,int (__cdecl *_PtFuncCompare)(const void *,const void *));
|
||||||
|
// --------------------------------------------------
|
||||||
|
// 1. 冒泡排序
|
||||||
|
bool bubble_sort(void* base, size_t count, size_t obj_size, compare_fun_t cmp);
|
||||||
|
// 2. 插入排序
|
||||||
|
bool insert_sort(void* base, size_t count, size_t obj_size, compare_fun_t cmp);
|
||||||
|
// 3. 快速排序
|
||||||
|
bool quick_sort(void* base, size_t count, size_t obj_size, compare_fun_t cmp);
|
||||||
|
// 4. 堆排序
|
||||||
|
bool heap_sort(void* base, size_t count, size_t obj_size, compare_fun_t cmp);
|
||||||
|
// 5. 归并排序
|
||||||
|
bool merge_sort(void* base, size_t count, size_t obj_size, compare_fun_t cmp);
|
||||||
|
// 6. 选择排序
|
||||||
|
bool select_sort(void* base, size_t count, size_t obj_size, compare_fun_t cmp);
|
||||||
|
// 7. 希尔排序
|
||||||
|
bool shell_sort(void* base, size_t count, size_t obj_size, compare_fun_t cmp);
|
||||||
|
|
||||||
|
// 非比较类排序
|
||||||
|
// 8. 基数排序
|
||||||
|
bool radix_sort(void* base, size_t count, size_t obj_size);
|
||||||
|
// 9. 桶排序
|
||||||
|
bool bucket_sort(void* base, size_t count, size_t obj_size);
|
||||||
|
// 10. 计数排序
|
||||||
|
bool counting_sort(void* base, size_t count, size_t obj_size);
|
||||||
|
|
||||||
|
// --------------------------------------------------
|
||||||
|
// 查找算法
|
||||||
|
// void *__cdecl bsearch(const void *_Key,const void *_Base,size_t _NumOfElements,size_t _SizeOfElements,int (__cdecl *_PtFuncCompare)(const void *,const void *));
|
||||||
|
// --------------------------------------------------
|
||||||
|
// 1. 线性查找
|
||||||
|
int linear_search(const void* key, const void* base, size_t count, size_t obj_size, compare_fun_t cmp);
|
||||||
|
|
||||||
|
// 2. 二分查找(默认左边界)
|
||||||
|
int binary_search(const void* key, const void* base, size_t count, size_t obj_size, compare_fun_t cmp);
|
||||||
|
// 3. 二分查找(右边界)
|
||||||
|
int binary_search_right(const void* key, const void* base, size_t count, size_t obj_size, compare_fun_t cmp);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef UNICSTL_ALGO
|
||||||
|
|
||||||
|
#ifdef UNICSTL_SORT
|
||||||
|
#define unicstl_sort(base, count, obj_size, cmp) \
|
||||||
|
quick_sort(base, count, obj_size, cmp)
|
||||||
|
#endif // UNICSTL_SORT
|
||||||
|
|
||||||
|
#ifdef UNICSTL_BSEARCH
|
||||||
|
#define unicstl_search(base, count, obj_size, key, cmp) \
|
||||||
|
binary_search(base, count, obj_size, key, cmp)
|
||||||
|
#endif // UNICSTL_BSEARCH
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#endif // UNICSTL_ALGO
|
||||||
|
|
||||||
|
#endif // _ALGO_H_
|
||||||
@ -29,13 +29,15 @@ struct _darray
|
|||||||
size_t _size;
|
size_t _size;
|
||||||
size_t _capacity;
|
size_t _capacity;
|
||||||
|
|
||||||
|
bool _sorted;
|
||||||
|
|
||||||
struct _iterator _iter;
|
struct _iterator _iter;
|
||||||
void (*_destory)(struct _darray *self);
|
void (*_destory)(struct _darray *self);
|
||||||
|
|
||||||
// -------------------- public --------------------
|
// -------------------- public --------------------
|
||||||
// kernel
|
// kernel
|
||||||
bool (*append)(struct _darray *self, const void *obj); // O(1)
|
bool (*append)(struct _darray *self, const void *obj); // O(1)
|
||||||
bool (*pop)(struct _darray *self, void *obj); // O(1)
|
bool (*pop)(struct _darray *self, void *obj); // O(1)
|
||||||
|
|
||||||
bool (*insert)(struct _darray *self, size_t index, const void *obj); // O(n)
|
bool (*insert)(struct _darray *self, size_t index, const void *obj); // O(n)
|
||||||
bool (*remove)(struct _darray *self, size_t index, void *obj); // O(n)
|
bool (*remove)(struct _darray *self, size_t index, void *obj); // O(n)
|
||||||
@ -45,9 +47,6 @@ struct _darray
|
|||||||
|
|
||||||
const void* (*at)(struct _darray *self, size_t index); // O(1)
|
const void* (*at)(struct _darray *self, size_t index); // O(1)
|
||||||
|
|
||||||
size_t (*index)(struct _darray *self, const void *obj); // O(n) retval -1 if not found
|
|
||||||
bool (*contains)(struct _darray *self, const void *obj); // O(n)
|
|
||||||
|
|
||||||
// base
|
// base
|
||||||
bool (*resize)(struct _darray *self, size_t capacity);
|
bool (*resize)(struct _darray *self, size_t capacity);
|
||||||
size_t (*size)(struct _darray *self);
|
size_t (*size)(struct _darray *self);
|
||||||
@ -56,6 +55,16 @@ struct _darray
|
|||||||
bool (*full)(struct _darray *self);
|
bool (*full)(struct _darray *self);
|
||||||
bool (*clear)(struct _darray *self);
|
bool (*clear)(struct _darray *self);
|
||||||
|
|
||||||
|
// sort and search
|
||||||
|
size_t (*index)(struct _darray *self, const void *obj); // O(n) return (size_t)-1 if not found
|
||||||
|
bool (*contains)(struct _darray *self, const void *obj); // O(n)
|
||||||
|
|
||||||
|
bool (*sort)(struct _darray *self); // O(nlogn)
|
||||||
|
size_t (*search)(struct _darray *self, const void *obj); // O(n) if not sorted; O(logn) if sorted
|
||||||
|
// return leftmost matched index; return (size_t)-1 if not found
|
||||||
|
|
||||||
|
size_t (*count)(struct _darray *self, const void *obj); // O(nlogn) if sorted; O(n) if not sorted
|
||||||
|
|
||||||
// iter
|
// iter
|
||||||
iterator_t (*iter)(struct _darray *self, enum _darray_order order);
|
iterator_t (*iter)(struct _darray *self, enum _darray_order order);
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,7 @@
|
|||||||
*/
|
*/
|
||||||
#ifndef _UNICSTL_CONFIG_H_
|
#ifndef _UNICSTL_CONFIG_H_
|
||||||
|
|
||||||
// #define NDEBUG // release
|
#define NDEBUG // release mode if define NDEBUG
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief unicstl contains which module
|
* @brief unicstl contains which module
|
||||||
|
|||||||
101
src/algo.c
Normal file
101
src/algo.c
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/**
|
||||||
|
* @file algo.c
|
||||||
|
* @author wenjf (Orig5826@163.com)
|
||||||
|
* @brief
|
||||||
|
* @version 0.1
|
||||||
|
* @date 2026-05-14
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2026
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include "algo.h"
|
||||||
|
|
||||||
|
// 1. 冒泡排序
|
||||||
|
bool bubble_sort(void* base, size_t count, size_t obj_size, compare_fun_t cmp)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 插入排序
|
||||||
|
bool insert_sort(void* base, size_t count, size_t obj_size, compare_fun_t cmp)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 快速排序
|
||||||
|
bool quick_sort(void* base, size_t count, size_t obj_size, compare_fun_t cmp)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 堆排序
|
||||||
|
bool heap_sort(void* base, size_t count, size_t obj_size, compare_fun_t cmp)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 归并排序
|
||||||
|
bool merge_sort(void* base, size_t count, size_t obj_size, compare_fun_t cmp)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. 选择排序
|
||||||
|
bool select_sort(void* base, size_t count, size_t obj_size, compare_fun_t cmp)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 7. 希尔排序
|
||||||
|
bool shell_sort(void* base, size_t count, size_t obj_size, compare_fun_t cmp)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 8. 基数排序
|
||||||
|
bool radix_sort(void* base, size_t count, size_t obj_size)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 9. 桶排序
|
||||||
|
bool bucket_sort(void* base, size_t count, size_t obj_size)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 10. 计数排序
|
||||||
|
bool counting_sort(void* base, size_t count, size_t obj_size)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int linear_search(const void* key, const void* base, size_t count, size_t obj_size, compare_fun_t cmp)
|
||||||
|
{
|
||||||
|
if (key == NULL)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
if (cmp((const char *)base + i * obj_size, (const char *)key) == 0)
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 二分查找(默认左边界)
|
||||||
|
int binary_search(const void* key, const void* base, size_t count, size_t obj_size, compare_fun_t cmp)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 二分找右边界:右边界
|
||||||
|
int binary_search_right(const void* key, const void* base, size_t count, size_t obj_size, compare_fun_t cmp)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
112
src/darray.c
112
src/darray.c
@ -9,6 +9,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#include "darray.h"
|
#include "darray.h"
|
||||||
|
#include "algo.h"
|
||||||
|
|
||||||
static size_t darray_size(struct _darray *self)
|
static size_t darray_size(struct _darray *self)
|
||||||
{
|
{
|
||||||
@ -120,6 +121,8 @@ static bool darray_insert(struct _darray *self, size_t index, const void *obj)
|
|||||||
// copy new data
|
// copy new data
|
||||||
memmove((char *)self->obj + offset, obj, self->_obj_size);
|
memmove((char *)self->obj + offset, obj, self->_obj_size);
|
||||||
self->_size += 1;
|
self->_size += 1;
|
||||||
|
|
||||||
|
self->_sorted = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,30 +191,6 @@ const void *darray_at(struct _darray *self, size_t index)
|
|||||||
return (const char *)self->obj + offset;
|
return (const char *)self->obj + offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t darray_index(struct _darray *self, const void *obj)
|
|
||||||
{
|
|
||||||
unicstl_assert(self != NULL);
|
|
||||||
if (obj == NULL)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < self->size(self); ++i)
|
|
||||||
{
|
|
||||||
if (self->compare((const char *)self->obj + i * self->_obj_size, (const char *)obj) == 0)
|
|
||||||
{
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool darray_contains(struct _darray *self, const void *obj)
|
|
||||||
{
|
|
||||||
unicstl_assert(self != NULL);
|
|
||||||
return darray_index(self, obj) != -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool darray_iter_hasnext(struct _iterator *iter)
|
bool darray_iter_hasnext(struct _iterator *iter)
|
||||||
{
|
{
|
||||||
unicstl_assert(iter != NULL);
|
unicstl_assert(iter != NULL);
|
||||||
@ -277,6 +256,85 @@ iterator_t darray_iter(struct _darray *self, enum _darray_order order)
|
|||||||
return iter;
|
return iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t darray_index(struct _darray *self, const void *obj)
|
||||||
|
{
|
||||||
|
unicstl_assert(self != NULL);
|
||||||
|
return self->search(self, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool darray_contains(struct _darray *self, const void *obj)
|
||||||
|
{
|
||||||
|
unicstl_assert(self != NULL);
|
||||||
|
return self->search(self, obj) != (size_t)-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool darry_sort(struct _darray *self)
|
||||||
|
{
|
||||||
|
unicstl_assert(self != NULL);
|
||||||
|
if(self->_sorted)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#ifdef UNICSTL_SORT
|
||||||
|
bubble_sort(self->obj, self->size(self), self->_obj_size, self->compare);
|
||||||
|
#else
|
||||||
|
qsort(self->obj, self->size(self), self->_obj_size, self->compare);
|
||||||
|
#endif
|
||||||
|
self->_sorted = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t darry_search(struct _darray *self, const void *obj)
|
||||||
|
{
|
||||||
|
unicstl_assert(self != NULL);
|
||||||
|
if(obj == NULL)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#ifdef UNICSTL_BSEARCH
|
||||||
|
if(self->_sorted)
|
||||||
|
{
|
||||||
|
return unicstl_search(obj, self->obj, self->size(self), self->_obj_size, self->compare);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if(self->_sorted)
|
||||||
|
{
|
||||||
|
bsearch(obj, self->obj, self->size(self), self->_obj_size, self->compare);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return linear_search(obj, self->obj, self->size(self), self->_obj_size, self->compare);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t darry_count(struct _darray *self, const void *obj)
|
||||||
|
{
|
||||||
|
unicstl_assert(self != NULL);
|
||||||
|
if(obj == NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
size_t count = 0;
|
||||||
|
size_t index = 0;
|
||||||
|
|
||||||
|
if(self->_sorted)
|
||||||
|
{
|
||||||
|
size_t index = self->search(self, obj);
|
||||||
|
if(index == (size_t)-1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(size_t i = index; i < self->size(self); i++)
|
||||||
|
{
|
||||||
|
if (self->compare((const char *)self->obj + i * self->_obj_size, (const char *)obj) != 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
static bool darray_init(struct _darray *self, size_t obj_size, size_t capacity)
|
static bool darray_init(struct _darray *self, size_t obj_size, size_t capacity)
|
||||||
{
|
{
|
||||||
unicstl_assert(self != NULL);
|
unicstl_assert(self != NULL);
|
||||||
@ -287,6 +345,8 @@ static bool darray_init(struct _darray *self, size_t obj_size, size_t capacity)
|
|||||||
self->_size = 0;
|
self->_size = 0;
|
||||||
self->_capacity = capacity;
|
self->_capacity = capacity;
|
||||||
|
|
||||||
|
self->_sorted = false;
|
||||||
|
|
||||||
self->obj = NULL;
|
self->obj = NULL;
|
||||||
self->_destory = darray_destory;
|
self->_destory = darray_destory;
|
||||||
|
|
||||||
@ -314,6 +374,10 @@ static bool darray_init(struct _darray *self, size_t obj_size, size_t capacity)
|
|||||||
// iter
|
// iter
|
||||||
self->iter = darray_iter;
|
self->iter = darray_iter;
|
||||||
|
|
||||||
|
// sort and search
|
||||||
|
self->sort = darry_sort;
|
||||||
|
self->search = darry_search;
|
||||||
|
|
||||||
// -------------------- default --------------------
|
// -------------------- default --------------------
|
||||||
self->print_obj = default_print_obj;
|
self->print_obj = default_print_obj;
|
||||||
|
|
||||||
|
|||||||
@ -571,6 +571,59 @@ static void test_darray_clear(void)
|
|||||||
darray_free(&darray);
|
darray_free(&darray);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_darray_sort(void)
|
||||||
|
{
|
||||||
|
int temp = 0;
|
||||||
|
int data[] = { 1,2,3,4,5,6,7,8,9,10 };
|
||||||
|
size_t len = sizeof(data) / sizeof(data[0]);
|
||||||
|
size_t i = 0;
|
||||||
|
int unordered_data[] = { 1, 3, 4, 5, 2, 9, 8, 10, 7, 6};
|
||||||
|
|
||||||
|
darray_t darray = darray_new(sizeof(int), len);
|
||||||
|
darray->compare = compare_num;
|
||||||
|
darray->print_obj = print_num;
|
||||||
|
|
||||||
|
for(i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
darray->append(darray, &unordered_data[i]);
|
||||||
|
}
|
||||||
|
TEST_ASSERT_TRUE(darray->sort(darray));
|
||||||
|
|
||||||
|
iterator_t iter = darray->iter(darray, DARRAY_FORWARD);
|
||||||
|
i = 0;
|
||||||
|
while(iter->hasnext(iter))
|
||||||
|
{
|
||||||
|
temp = *(int *)iter->next(iter);
|
||||||
|
TEST_ASSERT_EQUAL_INT(data[i], temp);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
TEST_ASSERT_EQUAL_INT(len, i);
|
||||||
|
|
||||||
|
temp = -55;
|
||||||
|
TEST_ASSERT_TRUE(darray->append(darray, &temp));
|
||||||
|
|
||||||
|
TEST_ASSERT_TRUE(darray->sort(darray));
|
||||||
|
|
||||||
|
iter = darray->iter(darray, DARRAY_FORWARD);
|
||||||
|
i = 0;
|
||||||
|
while(iter->hasnext(iter))
|
||||||
|
{
|
||||||
|
temp = *(int *)iter->next(iter);
|
||||||
|
if(i == 0)
|
||||||
|
{
|
||||||
|
TEST_ASSERT_EQUAL_INT(-55, temp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TEST_ASSERT_EQUAL_INT(data[i - 1], temp);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
TEST_ASSERT_EQUAL_INT(len + 1, i);
|
||||||
|
|
||||||
|
darray_free(&darray);
|
||||||
|
}
|
||||||
|
|
||||||
static void test_darray_struct(void)
|
static void test_darray_struct(void)
|
||||||
{
|
{
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
@ -638,7 +691,7 @@ void test_darray(void)
|
|||||||
RUN_TEST(test_darray_resize);
|
RUN_TEST(test_darray_resize);
|
||||||
RUN_TEST(test_darray_resize_invalid);
|
RUN_TEST(test_darray_resize_invalid);
|
||||||
|
|
||||||
RUN_TEST(test_darray_index);
|
RUN_TEST(test_darray_index); // index, search, contains
|
||||||
RUN_TEST(test_darray_index_invalid);
|
RUN_TEST(test_darray_index_invalid);
|
||||||
|
|
||||||
RUN_TEST(test_darray_at);
|
RUN_TEST(test_darray_at);
|
||||||
@ -647,6 +700,8 @@ void test_darray(void)
|
|||||||
|
|
||||||
RUN_TEST(test_darray_iter);
|
RUN_TEST(test_darray_iter);
|
||||||
|
|
||||||
|
RUN_TEST(test_darray_sort);
|
||||||
|
|
||||||
// ---------- base ----------
|
// ---------- base ----------
|
||||||
RUN_TEST(test_darray_clear);
|
RUN_TEST(test_darray_clear);
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user