feat(algo): 新增算法模块并给darray集成排序和查找功能,index底层改为调用search

This commit is contained in:
建峰 2026-05-15 00:04:04 +08:00
parent f8ba5197a8
commit d36346ce00
6 changed files with 338 additions and 31 deletions

78
include/algo.h Normal file
View 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_

View File

@ -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);

View File

@ -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
View 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)
{
}

View File

@ -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;

View File

@ -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);