c中的Reduce函数

x6yk4ghg  于 2023-01-08  发布在  其他
关注(0)|答案(2)|浏览(170)

因此,我正在尝试学习如何减少代码行,我遇到了我想看看的一个“更大”的函数。

int DTWDistance(int* x, int xsize, int* y, int ysize){
    const double LARGE_VALUE = 1e30;
    const int min_window = abs(xsize - ysize);
    int i, j, minj, maxj, window;
    double dist, min;
    double **distances = malloc((xsize + 1) * sizeof(double *));
    for(i = 0; i < xsize + 1; ++i)
        distances[i] = malloc((ysize + 1) * sizeof(double));

    window = 1*ysize;
    if(xsize > ysize)
        window = 1*xsize;

    if(window < min_window)
        window = min_window;

    for(i = 0; i <= xsize; ++i)
        for(j = 0; j <= ysize; ++j)
            distances[i][j] = LARGE_VALUE;

    distances[0][0] = 0;

    for(i = 0; i < xsize; ++i)
    {
        minj = i - window;
        if(minj < 0)
            minj = 0;
        maxj = i + window;
        if(maxj > ysize)
            maxj = ysize;
        for(j = minj; j < maxj; ++j)
        {
            dist = abs(x[i] - y[j]);
            min = distances[i][j];
            if(min > distances[i][j+1])
                min = distances[i][j+1];
            if(min > distances[i+1][j])
                min = distances[i+1][j];
            distances[i+1][j+1] = dist + min;
        }
    }

    dist = distances[xsize][ysize];

    for(i = 0; i < xsize + 1; ++i)
        free(distances[i]);
    free(distances);

    return dist;  
}

对我来说,它看起来不错,但可能是因为我已经看了太多次了,所以现在我想请一双新的眼睛来看看这个,你能想到一个更简单的方法来写这个吗?

注意:这是为了让我学习如何用另一种可能更聪明的方式编写代码?
编辑简化代码

//DTW - Dynamic Time Warping - Compare two -usually temporal- sequences
int DTWDistance(int* x, int xsize, int* y, int ysize){
    const int LARGE_VALUE = INT_MAX;
    int i, j, minj, maxj, fr, myMin, dist;
    int **distances = malloc((xsize + 1) * sizeof(int *));

    for(i = 0; i < xsize + 1; ++i)
        distances[i] = malloc((ysize + 1) * sizeof(int));

    for(i = 0; i <= xsize; ++i)
        for(j = 0; j <= ysize; ++j)
            distances[i][j] = LARGE_VALUE;

    distances[0][0] = 0;

    for(i = 0; i < xsize; ++i)
    {        
        minj = max(i - ysize, 0);
        maxj = min(i + ysize, ysize);
        
        for(j = minj; j < maxj; ++j)
        {
            dist = abs(x[i] - y[j]);
            fr =  min(distances[i][j + 1], distances[i + 1][j]);
            myMin = min(distances[i][j], fr);
            distances[i+1][j+1] = dist + myMin;
        }
    }

    dist = distances[xsize][ysize];

    for(i = 0; i < xsize + 1; ++i)
        free(distances[i]);
    free(distances);

    return dist;  
}
ktecyv1j

ktecyv1j1#

另一种简化方法是使用可变长度数组,如果xsize * ysize是合理的(最大大约100k),那么你可以使用VLA自动存储(通常在栈上分配)。
您可以替换:

double **distances = malloc((xsize + 1) * sizeof(double *));
    for(i = 0; i < xsize + 1; ++i)
        distances[i] = malloc((ysize + 1) * sizeof(double));

double distances[xsize + 1][ysize + 1];

并移除所有解除分配代码:

for(i = 0; i < xsize + 1; ++i)
        free(distances[i]);
    free(distances);

如果大小较大,则可以使用具有动态存储的VLA:

double (*distances)[ysize + 1] = malloc((xsize + 1) * sizeof *distances);

并在最后使用以下命令释放它:
free(distances)
与更流行的“数组的数组”相比,VLA还有其他优势。单个大的分配通常比一堆小的分配快得多。此外,访问真正的2D数组通常更适合缓存,并且更容易被编译器自动矢量化。

n53p2ov0

n53p2ov02#

如果使用minmax宏,可以减少很多代码:

#define min(a, b) ((a) < (b)) ? (a) : (b);
#define max(a, b) ((a) > (b)) ? (a) : (b);

这样就可以将其转换为一行:

// Old:
min = distances[i][j];
if(min > distances[i][j+1])
    min = distances[i][j+1];
if(min > distances[i+1][j])
    min = distances[i+1][j];

// New:
// note: renamed 'min' to avoid naming conflict with macro
myMin = min(distances[i][j], min(distances[i][j + 1], distances[i + 1][j]);

同样:

if(minj < 0)
    minj = 0;

可改为:

minj = max(i - window, 0);

以及:

if(maxj > ysize)
   maxj = ysize;

可能是:

maxj = min(i + window, ysize);

再次:

if(window < min_window)
    window = min_window;

可以是:

window = min(window, min_window);

这里,我把你的51行函数变成了40行函数。

相关问题