AMPD峰值检测C实现

以下是基于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;
}

算法优化说明‌:

  1. 内存安全
  • 增加所有malloc/calloc的返回值检查‌14
  • 使用calloc初始化计数数组避免脏数据
  • 严格限制窗口范围k < length -k防止越界‌34
  1. 性能优化
  • 窗口长度计算优化为(length/2)+1,避免冗余迭代‌23
  • 行和数组长度动态计算,减少内存占用‌4
  1. 鲁棒性增强
  • 处理输入数组长度小于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;
}

注意事项‌:

  1. 输入数组需满足data[i] != data[i+1]的假设条件‌7
  2. 输出数组需由调用方手动释放内存
  3. 返回-1表示内存分配失败,需进行错误处理‌14

该实现通过多阶段检测机制和动态窗口优化,在时间复杂度O(n²)与内存效率之间取得平衡,适用于嵌入式系统等资源受限场景‌。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GodenEngineer

你的赞赏,是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值