STC库中的优先级队列(pqueue)实现详解
概述
优先级队列(Priority Queue)是一种特殊的容器适配器,它能够提供对最大(默认)或最小元素的快速访问,同时保证插入和删除操作的高效性。STC库中的pqueue
模块实现了这一数据结构,其设计灵感来源于C++标准库中的std::priority_queue
。
核心特性
-
时间复杂度:
- 查看顶部元素(top):O(1)
- 插入元素(push):O(log n)
- 删除顶部元素(pop):O(log n)
-
自定义排序:
- 默认情况下,优先级队列维护最大堆特性
- 可通过
i_cmp
或i_less
宏定义自定义比较逻辑 - 使用
-c_default_cmp
可实现最小堆
头文件与声明
使用STC的优先级队列需要包含头文件<stc/pqueue.h>
,并通过宏定义配置队列行为:
// 基本定义方式
#define i_key <t> // 指定元素类型
#define i_less <fn> // 定义比较函数(必需,除非是基本类型)
#define i_cmp <fn> // 三路比较函数的替代方案
// 高级配置选项
#define i_keydrop <fn> // 自定义元素销毁函数
#define i_keyclone <fn> // 自定义元素克隆函数
#define i_keyraw <t> // 定义转换类型
#define i_keyfrom <fn> // 从原始类型转换
#define i_keytoraw <fn> // 转换为原始类型
主要API方法
初始化与销毁
pqueue_X_init() // 创建空队列
pqueue_X_with_capacity() // 预分配容量的队列
pqueue_X_clone() // 克隆队列
pqueue_X_drop() // 销毁队列
容量操作
pqueue_X_size() // 获取元素数量
pqueue_X_is_empty() // 检查是否为空
pqueue_X_reserve() // 预留空间
pqueue_X_shrink_to_fit() // 缩减容量
元素操作
pqueue_X_top() // 访问顶部元素
pqueue_X_push() // 插入元素
pqueue_X_emplace() // 就地构造元素
pqueue_X_pop() // 删除顶部元素
pqueue_X_pull() // 取出并返回顶部元素
pqueue_X_make_heap() // 堆化操作
实际应用示例
下面是一个使用优先级队列处理大量随机数的示例,展示了如何实现最小堆:
#include <stdio.h>
#include <stc/random.h>
// 定义最小堆优先级队列
#define T PriorityQ, int32
#define i_cmp -c_default_cmp // 负号表示最小堆
#include <stc/pqueue.h>
int main(void) {
const isize N = 10000000;
PriorityQ numbers = {0};
// 插入五百万个随机数
for (c_range(N/2))
PriorityQ_push(&numbers, (int32)(crand32_uint() >> 6));
// 插入一些特定负数
int32 nums[] = {-231, -32, -873, -4, -343};
for (c_range(i, c_countof(nums)))
PriorityQ_push(&numbers, nums[i]);
// 再插入五百万个随机数
for (c_range(N/2))
PriorityQ_push(&numbers, (int32)(crand32_uint() >> 6));
// 输出最小的50个数
for (c_range(50)) {
printf("%d ", *PriorityQ_top(&numbers));
PriorityQ_pop(&numbers);
}
PriorityQ_drop(&numbers);
}
性能优化建议
- 预分配空间:对于已知大小的队列,使用
pqueue_X_with_capacity
预先分配空间可避免多次扩容 - 批量操作:大量插入后调用
pqueue_X_make_heap
比单独插入更高效 - 内存管理:合理使用
shrink_to_fit
在稳定期减少内存占用
内部实现原理
STC的优先级队列底层基于动态数组实现,采用二叉堆的数据结构:
- 堆性质维护:每次插入(push)和删除(pop)操作后,通过上浮(sift up)和下沉(sift down)操作维护堆性质
- 内存管理:使用STC的智能指针系统自动管理元素生命周期
- 类型安全:通过宏系统在编译时生成类型特定的实现代码
适用场景
优先级队列特别适用于以下场景:
- 需要频繁获取最大/最小元素的场合
- 事件调度系统
- Dijkstra等图算法中的优先节点访问
- 实时系统中的任务优先级管理
通过STC库实现的优先级队列,开发者可以在C语言中获得与C++标准库相媲美的易用性和性能表现。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考