mirror of
https://gitee.com/apaki/unicstl.git
synced 2025-05-18 03:51:35 +08:00
Compare commits
5 Commits
9e270b7425
...
932b078778
Author | SHA1 | Date | |
---|---|---|---|
932b078778 | |||
1b5b69024e | |||
313406970c | |||
4c6387427b | |||
ca4ab10123 |
103
README.md
103
README.md
@ -1,13 +1,19 @@
|
|||||||
# unicstl
|
# unicstl
|
||||||
|
|
||||||
## 简介
|
## 简介
|
||||||
全称: Universal C standard library
|
基于C语言实现的通用C库,包含常用数据结构和算法。
|
||||||
|
|
||||||
基于C语言实现的通用C库。包含常用数据结构和算法
|
**全称:** Universal C standard library
|
||||||
|
|
||||||
> 标准:--std=c99
|
**作者:** 温建峰
|
||||||
|
|
||||||
[数据结构详细说明](https://blog.wenjianfeng.top)
|
**主页:** [博客](https://blog.wenjianfeng.top)
|
||||||
|
|
||||||
|
**邮箱:**[orig5826@163.com](mailto:orig5826@163.com)
|
||||||
|
|
||||||
|
## 编译环境
|
||||||
|
- 编译器:gcc 13.2.0
|
||||||
|
- 标准:--std=c99
|
||||||
|
|
||||||
## 数据结构
|
## 数据结构
|
||||||
|数据结构 | 原理 |说明 |
|
|数据结构 | 原理 |说明 |
|
||||||
@ -27,12 +33,81 @@
|
|||||||
| tree_rb_new | 二叉搜索树 | 红黑树 |
|
| tree_rb_new | 二叉搜索树 | 红黑树 |
|
||||||
| **heap** | |**堆** |
|
| **heap** | |**堆** |
|
||||||
| heap_new2 | 数组 | 最大堆/最小堆 |
|
| heap_new2 | 数组 | 最大堆/最小堆 |
|
||||||
|
| **graph** | |**图** |
|
||||||
|
| graph_new | 链表 | |
|
||||||
|
|
||||||
|
## 接口函数原型
|
||||||
|
```c
|
||||||
|
// -------------------- 初始化 --------------------
|
||||||
|
struct* new(...); // 创建
|
||||||
|
void free(struct**); // 释放
|
||||||
|
|
||||||
|
// 内部接口
|
||||||
|
// init 初始化 <构造函数>
|
||||||
|
// destory 销毁 <析构函数>
|
||||||
|
|
||||||
|
// 外部实现
|
||||||
|
int compare(void* obj1, void* obj2);// 比较函数,new后立刻配置(树、图必须)
|
||||||
|
|
||||||
|
// -------------------- 核心功能 --------------------
|
||||||
|
// 核心操作
|
||||||
|
bool push(const void* obj); // [栈、队列] 入栈/入队
|
||||||
|
bool push_front(const void* obj); // [双端队列] 头部入队
|
||||||
|
bool push_back(const void* obj); // [双端队列] 尾部入队
|
||||||
|
|
||||||
|
bool pop(void* obj); // [栈、队列] 出栈/出队
|
||||||
|
bool pop_front(void* obj); // [双端队列] 头部出队
|
||||||
|
bool pop_back(void* obj); // [双端队列] 尾部出队
|
||||||
|
|
||||||
|
bool peek(void* obj); // [栈] 查看栈顶元素
|
||||||
|
bool front(void* obj); // [队列、双端队列] 查看头部元素
|
||||||
|
bool back(void* obj); // [队列、双端队列] 查看尾部元素
|
||||||
|
|
||||||
|
// bool insert(const void* obj); // [树] 插入元素 <insert用于和位置相关操作>
|
||||||
|
// bool delete(const void* obj); // [树] 删除元素
|
||||||
|
|
||||||
|
// bool add_(const void* obj); // [图:顶点、边] 添加元素 <add不考虑位置关系>
|
||||||
|
// bool del_(const void* obj); // [图:顶点、边] 删除元素
|
||||||
|
// bool find_(const void* obj); // [图:顶点、边] 查找元素
|
||||||
|
|
||||||
|
// 基础操作
|
||||||
|
uint32_t size(); // 获取大小
|
||||||
|
bool empty(); // 判断是否为空
|
||||||
|
bool full(); // 判断是否为满
|
||||||
|
void clear(); // 清空
|
||||||
|
uint32_t capacity(); // [动态数组] 获取容量
|
||||||
|
|
||||||
|
// 迭代器操作
|
||||||
|
iterator_t iter(...); // 返回迭代器
|
||||||
|
bool iter_hasnext(); // 是否有下一个元素
|
||||||
|
void* iter_next(); // 迭代器下一个元素
|
||||||
|
|
||||||
|
// -------------------- 扩展功能 --------------------
|
||||||
|
// 元素相关操作
|
||||||
|
bool append(const void* obj); // 追加元素 <push_back> 一般用于list
|
||||||
|
bool delete(const void* obj); // 删除元素
|
||||||
|
// bool remove(const void *obj); // 删除元素 <同delete>
|
||||||
|
bool find(const void* obj); // 查找元素 <返回值,bool/uint32_t/void*待定?>
|
||||||
|
bool contains(const void* obj); // 判断元素是否存在 <返回bool>
|
||||||
|
uint32_t count(const void* obj); // 统计元素个数
|
||||||
|
|
||||||
|
// 索引相关操作
|
||||||
|
uint32_t index(void *obj); // 获取元素索引
|
||||||
|
bool insert(uint32_t index, const void* obj); // 插入元素 <非树>
|
||||||
|
bool erase(uint32_t index); // 删除元素
|
||||||
|
bool set(uint32_t index, const void* obj); // 设置元素
|
||||||
|
bool get(uint32_t index, void* obj); // 获取元素
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
## 特点
|
## 特点
|
||||||
| 原理 | 说明 |
|
| 原理 | 优势 | 弊端 |
|
||||||
| --- | --- |
|
| --- | --- |--- |
|
||||||
| 链表 | 有额外指针开销 |
|
| 链表 | 插入删除效率高 | 有额外指针开销 |
|
||||||
| 动态数组 | 扩容时数据搬移代价较大 |
|
| 动态数组 | 随机访问效率高 | 扩容时数据搬移代价较大 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| 单链表 | 适用内存受限场景 | 逆向不便 |
|
||||||
|
| 双向链表 | 频繁双向遍历的场景(如光标移动) | 空间开销大 |
|
||||||
|
|
||||||
|
|
||||||
## 性能比较
|
## 性能比较
|
||||||
@ -91,6 +166,18 @@ unicstl_stack_v1.2.5_20240717-a0.zip
|
|||||||
|
|
||||||
## 修改日志
|
## 修改日志
|
||||||
|
|
||||||
|
### Unicstl 0.0.02 (2025-04-24)
|
||||||
|
- new features
|
||||||
|
- graph add function: add/del/find vertex/edge
|
||||||
|
- graph add function: bfs/dfs
|
||||||
|
- tree remove old iterator and add new iterator
|
||||||
|
- deque add order select
|
||||||
|
- bugfixed:
|
||||||
|
- none
|
||||||
|
- others:
|
||||||
|
- none
|
||||||
|
|
||||||
|
|
||||||
### Unicstl 0.0.01 (2025-04-24)
|
### Unicstl 0.0.01 (2025-04-24)
|
||||||
- new features
|
- new features
|
||||||
- add stack
|
- add stack
|
||||||
|
@ -13,6 +13,12 @@
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
enum _deque_order
|
||||||
|
{
|
||||||
|
DEQUE_FORWARD,
|
||||||
|
DEQUE_REVERSE,
|
||||||
|
};
|
||||||
|
|
||||||
struct _deque_node
|
struct _deque_node
|
||||||
{
|
{
|
||||||
void* obj;
|
void* obj;
|
||||||
@ -50,7 +56,7 @@ struct _deque
|
|||||||
bool (*clear)(struct _deque* self);
|
bool (*clear)(struct _deque* self);
|
||||||
|
|
||||||
// iter
|
// iter
|
||||||
iterator_t (*iter)(struct _deque* self);
|
iterator_t (*iter)(struct _deque* self, enum _deque_order order);
|
||||||
|
|
||||||
// ohters
|
// ohters
|
||||||
bool (*insert)(struct _deque* self, int index, void* obj);
|
bool (*insert)(struct _deque* self, int index, void* obj);
|
||||||
|
@ -78,12 +78,11 @@ struct _graph
|
|||||||
bool (*del_edge)(struct _graph* self, void* from, void* to);
|
bool (*del_edge)(struct _graph* self, void* from, void* to);
|
||||||
bool (*find_edge)(struct _graph* self, void* from, void* to);
|
bool (*find_edge)(struct _graph* self, void* from, void* to);
|
||||||
|
|
||||||
bool (*empty)(struct _graph* self);
|
|
||||||
bool (*full)(struct _graph* self);
|
|
||||||
|
|
||||||
// base
|
// base
|
||||||
uint32_t(*size)(struct _graph* self);
|
uint32_t(*size)(struct _graph* self);
|
||||||
uint32_t(*capacity)(struct _graph* self);
|
uint32_t(*capacity)(struct _graph* self);
|
||||||
|
bool (*empty)(struct _graph* self);
|
||||||
|
bool (*full)(struct _graph* self);
|
||||||
bool (*clear)(struct _graph* self);
|
bool (*clear)(struct _graph* self);
|
||||||
|
|
||||||
// iter
|
// iter
|
||||||
|
@ -36,12 +36,12 @@ struct _heap
|
|||||||
|
|
||||||
// -------------------- public --------------------
|
// -------------------- public --------------------
|
||||||
// kernel
|
// kernel
|
||||||
bool (*peek)(struct _heap* self, void* obj);
|
|
||||||
bool (*push)(struct _heap* self, void* obj);
|
bool (*push)(struct _heap* self, void* obj);
|
||||||
bool (*pop)(struct _heap* self, void* obj);
|
bool (*pop)(struct _heap* self, void* obj);
|
||||||
bool (*empty)(struct _heap* self);
|
bool (*peek)(struct _heap* self, void* obj);
|
||||||
|
|
||||||
// base
|
// base
|
||||||
|
bool (*empty)(struct _heap* self);
|
||||||
uint32_t(*size)(struct _heap* self);
|
uint32_t(*size)(struct _heap* self);
|
||||||
bool (*clear)(struct _heap* self);
|
bool (*clear)(struct _heap* self);
|
||||||
|
|
||||||
|
@ -20,6 +20,8 @@ struct _iterator
|
|||||||
void* _cur_node;
|
void* _cur_node;
|
||||||
uint32_t _cur;
|
uint32_t _cur;
|
||||||
|
|
||||||
|
uint32_t _order;
|
||||||
|
|
||||||
// ---------- public ----------
|
// ---------- public ----------
|
||||||
bool (*hasnext)(struct _iterator* self);
|
bool (*hasnext)(struct _iterator* self);
|
||||||
const void* (*next)(struct _iterator* self);
|
const void* (*next)(struct _iterator* self);
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
/**
|
/**
|
||||||
* @file list.h
|
* @file list.h
|
||||||
* @author wenjf (Orig5826@163.com)
|
* @author wenjf (Orig5826@163.com)
|
||||||
* @brief
|
* @brief
|
||||||
* @version 0.1
|
* @version 0.1
|
||||||
* @date 2024-06-23
|
* @date 2024-06-23
|
||||||
*
|
*
|
||||||
* @copyright Copyright (c) 2024
|
* @copyright Copyright (c) 2024
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef _LIST_H_
|
#ifndef _LIST_H_
|
||||||
#define _LIST_H_
|
#define _LIST_H_
|
||||||
@ -16,8 +16,8 @@
|
|||||||
|
|
||||||
struct _list
|
struct _list
|
||||||
{
|
{
|
||||||
// -------------------- private --------------------
|
// -------------------- private --------------------
|
||||||
void * obj;
|
void *obj;
|
||||||
|
|
||||||
uint32_t _obj_size;
|
uint32_t _obj_size;
|
||||||
uint32_t _size;
|
uint32_t _size;
|
||||||
@ -27,27 +27,28 @@ struct _list
|
|||||||
|
|
||||||
struct _iterator _iter;
|
struct _iterator _iter;
|
||||||
|
|
||||||
void (*_destory)(struct _list* self);
|
void (*_destory)(struct _list *self);
|
||||||
|
|
||||||
// -------------------- public --------------------
|
// -------------------- public --------------------
|
||||||
// kernel
|
// kernel
|
||||||
bool (*append)(struct _list* self, void* obj); // Append object to the end of the list.
|
bool (*append)(struct _list *self, void *obj); // Append object to the end of the list.
|
||||||
bool (*insert)(struct _list* self, int index, void* obj); // Insert object before index.
|
bool (*insert)(struct _list *self, int index, void *obj); // Insert object before index.
|
||||||
bool (*pop)(struct _list* self, int index, void* obj); // Remove and return item at index.
|
bool (*pop)(struct _list *self, int index, void *obj); // Remove and return item at index.
|
||||||
|
|
||||||
int (*index)(struct _list* self, void* obj); // Return first index of obj. Return -1 if the obj is not present.
|
|
||||||
bool (*remove)(struct _list* self, void *obj); // Remove first occurrence of obj.
|
|
||||||
|
|
||||||
bool (*get)(struct _list* self, int index, void* obj);
|
int (*index)(struct _list *self, void *obj); // Return first index of obj. Return -1 if the obj is not present.
|
||||||
bool (*set)(struct _list* self, int index, void* obj);
|
bool (*remove)(struct _list *self, void *obj); // Remove first occurrence of obj.
|
||||||
|
|
||||||
|
bool (*get)(struct _list *self, int index, void *obj);
|
||||||
|
bool (*set)(struct _list *self, int index, void *obj);
|
||||||
|
|
||||||
// base
|
// base
|
||||||
uint32_t(*size)(struct _list* self);
|
uint32_t (*size)(struct _list *self);
|
||||||
bool (*empty)(struct _list* self);
|
uint32_t (*capacity)(struct _list *self);
|
||||||
bool (*clear)(struct _list* self);
|
bool (*empty)(struct _list *self);
|
||||||
|
bool (*clear)(struct _list *self);
|
||||||
|
|
||||||
// iter
|
// iter
|
||||||
iterator_t (*iter)(struct _list* self);
|
iterator_t (*iter)(struct _list *self);
|
||||||
|
|
||||||
// sort
|
// sort
|
||||||
// bool (*reverse)(struct _list* self); // Reverse *IN PLACE*.
|
// bool (*reverse)(struct _list* self); // Reverse *IN PLACE*.
|
||||||
@ -59,15 +60,15 @@ struct _list
|
|||||||
*/
|
*/
|
||||||
// bool (*sort)(struct _list* self, uint8_t reserve, int (*compare)(void* obj, void* obj2));
|
// bool (*sort)(struct _list* self, uint8_t reserve, int (*compare)(void* obj, void* obj2));
|
||||||
|
|
||||||
// -------------------- debug --------------------
|
// -------------------- debug --------------------
|
||||||
void (*print)(struct _list* self);
|
void (*print)(struct _list *self);
|
||||||
void (*print_obj)(void* obj);
|
void (*print_obj)(void *obj);
|
||||||
};
|
};
|
||||||
typedef struct _list* list_t;
|
typedef struct _list *list_t;
|
||||||
|
|
||||||
// create and free list
|
// create and free list
|
||||||
list_t list_new2(uint32_t obj_size, uint32_t capacity);
|
list_t list_new2(uint32_t obj_size, uint32_t capacity);
|
||||||
|
|
||||||
void list_free(list_t* list);
|
void list_free(list_t *list);
|
||||||
|
|
||||||
#endif // _LIST_H_
|
#endif // _LIST_H_
|
||||||
|
@ -43,11 +43,11 @@ struct _stack
|
|||||||
bool (*push)(struct _stack* self, void* obj);
|
bool (*push)(struct _stack* self, void* obj);
|
||||||
bool (*pop)(struct _stack* self, void* obj);
|
bool (*pop)(struct _stack* self, void* obj);
|
||||||
bool (*peek)(struct _stack* self, void* obj);
|
bool (*peek)(struct _stack* self, void* obj);
|
||||||
bool (*empty)(struct _stack* self);
|
|
||||||
|
|
||||||
// base
|
// base
|
||||||
uint32_t (*size)(struct _stack* self);
|
uint32_t (*size)(struct _stack* self);
|
||||||
uint32_t (*capacity)(struct _stack* self);
|
uint32_t (*capacity)(struct _stack* self);
|
||||||
|
bool (*empty)(struct _stack* self);
|
||||||
bool (*clear)(struct _stack* self);
|
bool (*clear)(struct _stack* self);
|
||||||
|
|
||||||
// iter
|
// iter
|
||||||
|
31
src/deque.c
31
src/deque.c
@ -295,14 +295,22 @@ static void deque_print(struct _deque* self)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator_t deque_iter(struct _deque* self)
|
iterator_t deque_iter(struct _deque* self, enum _deque_order order)
|
||||||
{
|
{
|
||||||
assert(self != NULL);
|
assert(self != NULL);
|
||||||
iterator_t iter = &self->_iter;
|
iterator_t iter = &self->_iter;
|
||||||
|
|
||||||
iter->_parent = self;
|
iter->_parent = self;
|
||||||
iter->_cur = 0;
|
iter->_cur = 0;
|
||||||
iter->_cur_node = self->_head;
|
iter->_order = order;
|
||||||
|
if(iter->_order == DEQUE_FORWARD)
|
||||||
|
{
|
||||||
|
iter->_cur_node = self->_head;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iter->_cur_node = self->_tail;
|
||||||
|
}
|
||||||
return iter;
|
return iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -327,13 +335,22 @@ const void* deque_iter_next(struct _iterator* iter)
|
|||||||
deque_t self = (deque_t)iter->_parent;
|
deque_t self = (deque_t)iter->_parent;
|
||||||
void *obj = NULL;
|
void *obj = NULL;
|
||||||
|
|
||||||
// base on linklist
|
struct _deque_node * cur_node = (struct _deque_node *)iter->_cur_node;
|
||||||
struct _deque_node * node = (struct _deque_node *)iter->_cur_node;
|
if(cur_node == NULL)
|
||||||
if(node != NULL)
|
|
||||||
{
|
{
|
||||||
obj = node->obj;
|
return NULL;
|
||||||
iter->_cur_node = node->next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
obj = cur_node->obj;
|
||||||
|
if(iter->_order == DEQUE_FORWARD)
|
||||||
|
{
|
||||||
|
iter->_cur_node = cur_node->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iter->_cur_node = cur_node->prev;
|
||||||
|
}
|
||||||
|
|
||||||
self->_iter._cur += 1;
|
self->_iter._cur += 1;
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
@ -267,7 +267,7 @@ static void test_deque_struct(void)
|
|||||||
static void test_deque_iter(void)
|
static void test_deque_iter(void)
|
||||||
{
|
{
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
int data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
int data[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||||
int temp = 0;
|
int temp = 0;
|
||||||
uint32_t len = sizeof(data) / sizeof(data[0]);
|
uint32_t len = sizeof(data) / sizeof(data[0]);
|
||||||
|
|
||||||
@ -288,26 +288,33 @@ static void test_deque_iter(void)
|
|||||||
TEST_ASSERT_EQUAL_INT(i + 1, deque->size(deque));
|
TEST_ASSERT_EQUAL_INT(i + 1, deque->size(deque));
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator_t iter = deque->iter(deque);
|
iterator_t iter = deque->iter(deque, DEQUE_FORWARD);
|
||||||
i = 0;
|
i = 0;
|
||||||
while(iter->hasnext(iter))
|
while(iter->hasnext(iter))
|
||||||
{
|
{
|
||||||
temp = *(int *)iter->next(iter);
|
temp = *(int *)iter->next(iter);
|
||||||
// printf("%d ", temp);
|
|
||||||
TEST_ASSERT_EQUAL_INT(data[i], temp);
|
TEST_ASSERT_EQUAL_INT(data[i], temp);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
iter = deque->iter(deque);
|
iter = deque->iter(deque, DEQUE_FORWARD);
|
||||||
i = 0;
|
i = 0;
|
||||||
while(iter->hasnext(iter))
|
while(iter->hasnext(iter))
|
||||||
{
|
{
|
||||||
temp = *(int *)iter->next(iter);
|
temp = *(int *)iter->next(iter);
|
||||||
// printf("%d ", temp);
|
|
||||||
TEST_ASSERT_EQUAL_INT(data[i], temp);
|
TEST_ASSERT_EQUAL_INT(data[i], temp);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iter = deque->iter(deque, DEQUE_REVERSE);
|
||||||
|
i = len - 1;
|
||||||
|
while(iter->hasnext(iter))
|
||||||
|
{
|
||||||
|
temp = *(int *)iter->next(iter);
|
||||||
|
TEST_ASSERT_EQUAL_INT(data[i], temp);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
|
||||||
deque_free(&deque);
|
deque_free(&deque);
|
||||||
TEST_ASSERT_NULL(deque);
|
TEST_ASSERT_NULL(deque);
|
||||||
}
|
}
|
||||||
|
@ -149,7 +149,7 @@ void test_graph_iter(void)
|
|||||||
TEST_ASSERT_TRUE(graph->add_edge(graph, &data[7], &data[6], 87));
|
TEST_ASSERT_TRUE(graph->add_edge(graph, &data[7], &data[6], 87));
|
||||||
TEST_ASSERT_TRUE(graph->add_edge(graph, &data[8], &data[2], 92));
|
TEST_ASSERT_TRUE(graph->add_edge(graph, &data[8], &data[2], 92));
|
||||||
TEST_ASSERT_FALSE(graph->add_edge(graph, &temp, &data[1], 0));
|
TEST_ASSERT_FALSE(graph->add_edge(graph, &temp, &data[1], 0));
|
||||||
graph->print(graph);
|
// graph->print(graph);
|
||||||
|
|
||||||
iterator_t iter_vertex = NULL;
|
iterator_t iter_vertex = NULL;
|
||||||
|
|
||||||
@ -158,18 +158,18 @@ void test_graph_iter(void)
|
|||||||
while(iter_vertex->hasnext(iter_vertex))
|
while(iter_vertex->hasnext(iter_vertex))
|
||||||
{
|
{
|
||||||
temp = *(int *)iter_vertex->next(iter_vertex);
|
temp = *(int *)iter_vertex->next(iter_vertex);
|
||||||
graph->print_obj(&temp);
|
//graph->print_obj(&temp);
|
||||||
}
|
}
|
||||||
printf("\n");
|
//printf("\n");
|
||||||
|
|
||||||
iter_vertex = graph->iter(graph, GRAPH_DFS, &data[0]);
|
iter_vertex = graph->iter(graph, GRAPH_DFS, &data[0]);
|
||||||
TEST_ASSERT_NOT_NULL(iter_vertex);
|
TEST_ASSERT_NOT_NULL(iter_vertex);
|
||||||
while(iter_vertex->hasnext(iter_vertex))
|
while(iter_vertex->hasnext(iter_vertex))
|
||||||
{
|
{
|
||||||
temp = *(int *)iter_vertex->next(iter_vertex);
|
temp = *(int *)iter_vertex->next(iter_vertex);
|
||||||
graph->print_obj(&temp);
|
//graph->print_obj(&temp);
|
||||||
}
|
}
|
||||||
printf("\n");
|
//printf("\n");
|
||||||
|
|
||||||
graph_free(&graph);
|
graph_free(&graph);
|
||||||
TEST_ASSERT_NULL(graph);
|
TEST_ASSERT_NULL(graph);
|
||||||
|
Loading…
Reference in New Issue
Block a user