C保持运行信号数组排序

时间:2016-05-20 11:42:56

标签: c arrays sorting

我试图提高当前程序的速度,该程序记录来自多个传感器的数据,但具体的一部分非常慢。

在这部分中,我将信号数据存储在大小为50的整数数组中,并提取最大值和最小值以获得幅度的(粗略)指示。这是针对每秒3个传感器完成的,但是对阵列进行排序以获得最小值和最大值需要很长时间。

我的第一个想法是将数据存储在排序列表中,但是如何跟踪必须删除的最后一个信号点是什么?

当前代码:

    static int movement[AD_SENSORS][AD_MOVEMENT_SIZE];
    static int totals[AD_SENSORS];
    int movement_sorted[AD_MOVEMENT_SIZE];
    int difference = 0;
    static unsigned int i; // Movement index
    int k = 0;

    //Update positions
    if (++i>(AD_MOVEMENT_SIZE-1)){i=0;} //increment index of movement array

    //Initialise signal value
    struct tty_data_t *Current = NULL;
    Current = head_tty;

    //Add signals to movement array
    while (Current != NULL){
        totals[Current->ID] = totals[Current->ID] - movement[Current->ID][i];
        movement[Current->ID][i] = Current->AD_signal;
        totals[Current->ID] = totals[Current->ID] + movement[Current->ID][i];
        Current->AD_average = totals[Current->ID] / AD_MOVEMENT_SIZE;
        for (k = 0; k<AD_MOVEMENT_SIZE; k++){
            movement_sorted[k] = movement[Current->ID][k];
        }
        qsort (movement_sorted, AD_MOVEMENT_SIZE, sizeof(int), Compare);
        Current->AD_amplitude = movement_sorted[AD_MOVEMENT_SIZE-1] - movement_sorted[0];
        difference += movement_sorted[AD_MOVEMENT_SIZE-1] - movement_sorted[0];
        Current = Current->next;
    }
    g_movement = difference;

2 个答案:

答案 0 :(得分:1)

排序五十个元素不应该花很长时间,它应该能够在三分之一秒内完成。

但是,您可能实际上不需要进行排序。假设您有最后50个元素的滚动数组,您只需要调整minmax(以及与它们匹配的元素数mincountmaxcount)在有限的情况下。我将为您提供最大值的步骤,但也可以轻松地将逻辑复制到最小值。这些都是相互排斥的情况,应按给定的顺序进行检查(您发现的第一场比赛排除了其后的所有其他比赛):

  • 将元素添加到空列表时,请将max设置为该元素,并将maxcount设置为1。
  • 如果您要添加相同的值,则不执行任何操作。
  • 如果您要添加的值与max相同,只需在maxcount中添加一个。
  • 如果您要添加的值大于当前max,请将max设置为该值,并将maxcount设置为1。 如果您要移除的值与max相同且maxcount大于1,则只需递减maxcount
  • 否则,如果您要删除的值等于当前max(此时maxcount必须为1),请扫描列表中的项目以重新计算新{{1}并相应地设置计数。

唯一的可能代价高昂的选项是最后一个,我希望它很少发生。在任何情况下,每次迭代搜索一个大小为50的数组并进行几次比较仍然应该非常快。

并且不要关注性能。即使是每秒100个读数的8个传感器,每个也只能提供800个数据点。由于数据集很小,排序可能是一个愚蠢的差事,因为按顺序扫描许多项目仍然会非常快(特别是如果您不必每次时间更新滚动数据)。

答案 1 :(得分:1)

如果您要排序只是为了获得最大值和最小值而不是问题中未包含的其他原因,那么您不需要。 您的代码中已经有以下循环:

for (k = 0; k < AD_MOVEMENT_SIZE; k++){
            movement_sorted[k] = movement[Current->ID][k];
        }

而不是复制数组以对其进行排序(在O(nlogn)时间内),只需检查每个元素是最大值还是最小值,并在O(n)时间内获取它们。

int max = INT_MIN;
int min = INT_MAX;
for (k = 0; k<AD_MOVEMENT_SIZE; k++){
            if (movement[Current->ID][k] < min) min = movement[Current->ID][k];
            if (movement[Current->ID][k] > max) max = movement[Current->ID][k];
        }

免责声明:我知道big-O表示法在50个元素的数组中没有说太多,但在更一般的情况下它很重要