mirror of
https://gitee.com/apaki/unicstl.git
synced 2026-05-28 22:54:19 +08:00
- 重构迭代器顺序枚举,引入 linear_order_t、tree_order_t 等通用类型,并替换。 - 修复 darray 中二分查找返回索引计算错误的问题 - 优化 segarray 的内存分配错误处理 - 增强 logger 模块,支持时间戳打印及格式化输出 |
||
|---|---|---|
| .. | ||
| notes.md | ||
| PERF.md | ||
| README.md | ||
| unicstl.log | ||
unicstl
编译环境
- 编译器:gcc 13.2.0
- 标准:--std=c99
特点
| 原理 | 优势 | 弊端 |
|---|---|---|
| 链表 | 插入删除效率高 | 有额外指针开销 |
| 动态数组 | 随机访问效率高 | 扩容时数据搬移代价较大 |
| --- | --- | --- |
| 单链表 | 适用内存受限场景 | 逆向不便 |
| 双向链表 | 频繁双向遍历的场景(如光标移动) | 空间开销大 |
性能比较
| 数据结构 | < | 时 | 间 | 复 | 杂 | 度 | > | <空间复杂度> | |
|---|---|---|---|---|---|---|---|---|---|
| --- | ( | 平 | 均 | ) | ( | 最 | 坏 | ) | 最坏 |
| --- | 访问 | 搜索 | 插入 | 删除 | 访问 | 搜索 | 插入 | 删除 | --- |
| 数组 | O(1) |
O(n) |
O(n) |
O(n) |
O(1) |
O(n) |
O(n) |
O(n) |
O(n) |
| 栈 | O(n) |
O(n) |
O(1) |
O(1) |
O(n) |
O(n) |
O(1) |
O(1) |
O(n) |
| 队列 | O(n) |
O(n) |
O(1) |
O(1) |
O(n) |
O(n) |
O(1) |
O(1) |
O(n) |
| 单向链表 | O(n) |
O(n) |
O(1) |
O(1) |
O(n) |
O(n) |
O(1) |
O(1) |
O(n) |
| 双向链表 | O(n) |
O(n) |
O(1) |
O(1) |
O(n) |
O(n) |
O(1) |
O(1) |
O(n) |
| 跳表 | O(log(n)) |
O(log(n)) |
O(log(n)) |
O(log(n)) |
O(n) |
O(n) |
O(n) |
O(n) |
O(n*log(n)) |
| 哈希表 | N/A |
O(1) |
O(1) |
O(1) |
N/A |
O(n) |
O(n) |
O(n) |
O(n) |
| 二叉搜索树 | O(log(n)) |
O(log(n)) |
O(log(n)) |
O(log(n)) |
O(n) |
O(n) |
O(n) |
O(n) |
O(n) |
| AVL树 | O(log(n)) |
O(log(n)) |
O(log(n)) |
O(log(n)) |
O(log(n)) |
O(log(n)) |
O(log(n)) |
O(log(n)) |
O(n) |
| 红黑树 | O(log(n)) |
O(log(n)) |
O(log(n)) |
O(log(n)) |
O(log(n)) |
O(log(n)) |
O(log(n)) |
O(log(n)) |
O(n) |
| B树 | O(log(n)) |
O(log(n)) |
O(log(n)) |
O(log(n)) |
O(log(n)) |
O(log(n)) |
O(log(n)) |
O(log(n)) |
O(n) |
【答疑】 若链表的操作流程为,先查找元素再删除元素。那么时间复杂度确实是$O(n)$。但是链表的增删优势,在其他应用有体现。比如双向队列,插入和删除效率都为$O(1)$。
规范
版本说明
| 命名 | 版本说明 | 范围 | 更新说明 |
|---|---|---|---|
VERSION_MAJOR |
主版本号 | 0 ~ 99 | 代码框架大改,完全不兼容旧版 |
VERSION_MINOR |
次版本号 | 0 ~ 99 | 代码框架尽量兼容旧版,增信大功能、修复重大bug等 |
VERSION_MICRO |
小版本号 | 0 ~ 99 | 代码框架兼容旧版,新增小功能、修复bug等 |
举例说明:
// 若 major > 0 ,则代表正式发布版本
#define UNICSTL_VERSION_MAJOR 1
#define UNICSTL_VERSION_MINOR 2
#define UNICSTL_VERSION_MICRO 5
#define UNICSTL_VERSION ((UNICSTL_VERSION_MAJOR << 16) | (UNICSTL_VERSION_MINOR << 8) | UNICSTL_VERSION_MICRO)
工程命名
工程名(_功能)_v版本号_日期(_时间)(-其他信息)
括号内表示可选项
| 其他信息后缀 | 说明 | 详细 |
|---|---|---|
| aX | alpha内测版 | 可能仅测试了新增功能,但没有测试新增功能对其他模块的影响 |
| bX | beta公测版 | 不仅测试了新增功能,也测试了其他模块,尽量保证新增的功能不影响原来的旧功能。 |
| ... | 或者添加其他有有效信息 |
举例说明:
unicstl_stack_v1.2.5_20240717-a0.zip
# 带a或者b后缀,表示当前版本发布前的测试版。如果发布后,则直接更新版本号了
deque实现对比
segarray类比c++的deque,ringbuf类比rust的VecDeque
若capacity足够,不需要扩容
| 场景 | ringbuf | segarray | 说明 |
|---|---|---|---|
| size < capacity/2 | 无扩容 | 无扩容 | 性能一样 |
| size > capacity/2 | 无扩容 | 内部预留耗尽,触发段/map分配 | ringBuf连续内存缓存更优,segarray因中段起始预留,不库容容量折半 |
若capacity不够,需要扩容
- capacity 合理的情况下(初值预估可能大小)
| 场景 | ringbuf | segarray | 说明 |
|---|---|---|---|
| objsize 很大 | 按倍数扩整体连续大内存 + 全量数据搬移 | 新分配小段、无旧数据拷贝,顶多map指针数组扩容 | segarray 碾压,规避巨型对象整体拷贝开销 |
| objsize 很小 | 倍数扩容开销极低,连续内存缓存友好 | 逐段分配、map偶尔扩容,间接寻址拖累缓存 | ringBuf占优;小对象拷贝成本可忽略,连续内存优势拉满 |
备注:C++标准库 deque 靠固定 512 字节自适应每段元素数。也即可以让segarray 借助 objsize 和 512 对比,来实现方案优化
- capacity 非常小情况
| 场景 | ringbuf | segarray | 说明 |
|---|---|---|---|
| objsize 很大 | 每次翻倍扩连续巨块内存 + 大批量搬移大对象 | 每次只按需分配单个,少量段,永远不拷贝旧数据 | segarray 依然优势明显 |
| objsize 很小 | 指数倍数扩容,扩容次数少、成本低 | 退化成「类链表模式」:每插易新建段 + 频繁小分配,虽支持随机访问,但内存碎片化、分配次数暴增 | ringBuf 完胜,翻倍扩容策略吊打退化的 SegArray |