【问题标题】:sort array in C, return sorted indices在 C 中对数组进行排序,返回排序后的索引
【发布时间】:2018-04-08 08:19:40
【问题描述】:

我正在使用来自 https://phoxis.org/2012/07/12/get-sorted-index-orderting-of-an-array/ 的示例,其中他从某种数组中返回排序索引,即

3,4,2,6,8 返回4,3,1,0,2(R 中的每个索引+1)。这相当于R的order函数

我已经将他/她的代码翻译成一个返回排序索引数组的函数。代码给出了正确答案。

keeping track of the original indices of an array after sorting in C 有类似的响应,但正如@BLUEPIXY 警告的那样,他的解决方案并非在所有情况下都有效。我需要在所有情况下都有效的东西,包括领带。

但是,原作者使用了全局指针,导致内存泄漏,free() 并没有修复它。如果没有全局指针,我不知道该怎么做。

如何解决此内存泄漏问题,或者至少在 C 中返回始终有效的排序索引?

#include <stdio.h>
#include <stdlib.h>

/* holds the address of the array of which the sorted index
 * order needs to be found
 */
int * base_arr = NULL;
/* Note how the compare function compares the values of the
 * array to be sorted. The passed value to this function
 * by `qsort' are actually the `idx' array elements.
 */
static int compar_increase (const void * a, const void * b) {
    int aa = *((int * ) a), bb = *((int *) b);
    if (base_arr[aa] < base_arr[bb]) {
        return 1;
    } else if (base_arr[aa] == base_arr[bb]) {
        return 0;
    } else {
//  if (base_arr[aa] > base_arr[bb])
        return -1;
     }
}

int * order_int (const int * ARRAY, const size_t SIZE) {
    int * idx = malloc(SIZE * sizeof(int));
    base_arr = malloc(sizeof(int) * SIZE);
    for (size_t i = 0; i < SIZE; i++) {
        base_arr[i] = ARRAY[i];
        idx[i] = i;
    }
    qsort(idx, SIZE, sizeof(int), compar_increase);
    free(base_arr); base_arr = NULL;
    return idx;
}


int main () {
    const int a[] = {3,4,2,6,8};
    int * b = malloc(sizeof(int) * sizeof(a) / sizeof (*a));
    b = order_int(a, sizeof(a) / sizeof(*a));
    for (size_t i = 0; i < sizeof(a)/sizeof(*a); i++) {
        printf("b[%lu] = %d\n", i, b[i]+1);
    }
    free(b); b = NULL;
    return 0;
}

【问题讨论】:

  • 回答你的问题的方法太多了。
  • 一条建议 con - 您不需要为指针 b 分配内存 - 因为 order_int(..) 返回一个已分配内存的指针。
  • @Neil,哇,原来如此!你能把你的解决方案写下来,这样我可以给你绿色的复选标记吗?只需将int * b = malloc(sizeof(int) * sizeof(a) / sizeof (*a)); 更改为int * b;

标签: c arrays sorting


【解决方案1】:

不使用全局变量的直接方法如下所示

#include <stdio.h>
#include <stdlib.h>

int cmp_ptr(const void *a, const void *b)
{
    const int **left  = (const int **)a;
    const int **right = (const int **)b;

    return (**left < **right) - (**right < **left);
}

size_t * order_int(const int *a, size_t n)
{
    const int **pointers = malloc(n * sizeof(const int *));

    for (size_t i = 0; i < n; i++) pointers[i] = a + i;

    qsort(pointers, n, sizeof(const int *), cmp_ptr);

    size_t *indices = malloc(n * sizeof(size_t));

    for (size_t i = 0; i < n; i++) indices[i] = pointers[i] - a;

    free(pointers);

    return indices;
}

int main( void )
{
    const int a[] = { 3,4,2,6,8 };
    const size_t N = sizeof(a) / sizeof(*a);
    size_t *indices = order_int(a, N);

    for (size_t i = 0; i < N; i++) printf("%d ", a[indices[i]]);
    putchar('\n');

    free(indices);

    return 0;
}

程序输出是

8 6 4 3 2 

至于内存泄漏,那是由于覆盖了指向冗余分配内存的指针的值。

int * b = malloc(sizeof(int) * sizeof(a) / sizeof (*a));
b = order_int(a, sizeof(a) / sizeof(*a));

内存分配没有意义。

【讨论】:

    【解决方案2】:

    我看到的问题是在 main 函数中 - 你正在为指针 b 分配一些内存 -

       int * b = malloc(sizeof(int) * sizeof(a) / sizeof (*a));
    

    下一行调用 order_int(...) 返回一个指向已分配内存的指针 -

      b = order_int(a, sizeof(a) / sizeof(*a));
    

    看order_int函数——

    int * order_int (const int * ARRAY, const size_t SIZE) {
        int * idx = malloc(SIZE * sizeof(int));
        base_arr = malloc(sizeof(int) * SIZE);
        for (size_t i = 0; i < SIZE; i++) {
            base_arr[i] = ARRAY[i];
            idx[i] = i;
        }
        qsort(idx, SIZE, sizeof(int), compar_increase);
        free(base_arr); base_arr = NULL;
        return idx;
    }
    

    .. 你看到 idx 已经被分配了正确的内存。

    我建议从 b 中删除 malloc - 见下文。

      int * b = NULL;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-04-27
      • 2015-05-13
      • 2011-08-03
      • 1970-01-01
      • 2019-06-25
      • 2017-11-02
      相关资源
      最近更新 更多