以下是基于AMPD算法实现的双精度数组峰值检测C代码,结合了多篇文献优化后的鲁棒性实现:
#include <stdlib.h>
#include <math.h>
// 寻找数组最小值的索引(优化内存访问)
static int argmin(const int* arr, int len) {
int min_val = arr, min_idx = 0;
for (int i = 1; i < len; ++i) {
if (arr[i] < min_val) {
min_val = arr[i];
min_idx = i;
}
}
return min_idx;
}
/**
* @brief AMPD峰值检测核心算法
* @param data 输入数组(双精度浮点型)
* @param length 数组长度
* @param peaks 输出峰值索引数组
* @return 检测到的峰值数量(返回-1表示内存分配失败)
*/
int AMPD(double* data, int length, int** peaks) {
if (length < 2) return 0;
// 初始化行和数组
const int max_k = (length / 2) + 1;
int* arr_rowsum = (int*)malloc(max_k * sizeof(int));
if (!arr_rowsum) return -1;
// 阶段1:确定最佳窗口长度
for (int k = 1; k < max_k; ++k) {
int row_sum = 0;
for (int i = k; i < length - k; ++i) {
if (data[i] > data[i - k] && data[i] > data[i + k])
row_sum--;
}
arr_rowsum[k] = row_sum;
}
// 获取最优窗口长度
const int optimal_win = argmin(arr_rowsum, max_k);
free(arr_rowsum);
// 阶段2:执行峰值检测
int* peak_counts = (int*)calloc(length, sizeof(int));
if (!peak_counts) return -1;
for (int k = 1; k <= optimal_win; ++k) {
for (int i = k; i < length - k; ++i) {
if (data[i] > data[i - k] && data[i] > data[i + k])
peak_counts[i]++;
}
}
// 收集有效峰值索引
int peak_num = 0;
for (int i = 0; i < length; ++i) {
if (peak_counts[i] == optimal_win)
peak_num++;
}
*peaks = (int*)malloc(peak_num * sizeof(int));
if (!*peaks) {
free(peak_counts);
return -1;
}
for (int i = 0, j = 0; i < length; ++i) {
if (peak_counts[i] == optimal_win)
(*peaks)[j++] = i;
}
free(peak_counts);
return peak_num;
}
算法优化说明:
- 内存安全
- 增加所有
malloc/calloc
的返回值检查14 - 使用
calloc
初始化计数数组避免脏数据 - 严格限制窗口范围
k < length -k
防止越界34
- 性能优化
- 窗口长度计算优化为
(length/2)+1
,避免冗余迭代23 - 行和数组长度动态计算,减少内存占用4
- 鲁棒性增强
- 处理输入数组长度小于2的边界情况1
- 双阶段检测机制确保峰值有效性13
- 动态内存分配峰值数组,调用方需负责释放
使用示例:
int main() {
double data[] = {1.0, 3.0, 7.0, 4.0, 2.0, 9.0, 5.0};
int* peaks = NULL;
const int count = AMPD(data, 7, &peaks);
if (count > 0) {
printf("检测到%d个峰值:", count);
for (int i = 0; i < count; ++i)
printf("%d ", peaks[i]);
}
free(peaks);
return 0;
}
注意事项:
- 输入数组需满足
data[i] != data[i+1]
的假设条件7 - 输出数组需由调用方手动释放内存
- 返回-1表示内存分配失败,需进行错误处理14
该实现通过多阶段检测机制和动态窗口优化,在时间复杂度O(n²)与内存效率之间取得平衡,适用于嵌入式系统等资源受限场景。