在C中排序后跟踪数组的原始索引

Posted

技术标签:

【中文标题】在C中排序后跟踪数组的原始索引【英文标题】:keeping track of the original indices of an array after sorting in C 【发布时间】:2014-08-26 12:19:13 【问题描述】:

我有一个数组,比如说A[5],5 个元素是5,4,1,2,3。现在我按升序对这些数组进行排序。所以结果数组现在将是1,2,3,4,5。我使用stdlib.hqsort() 函数对其进行排序。问题是如何获得原始数组相对于我的新数组的索引。最初我的索引是0,1,2,3,4 对应的5,4,1,2,3 值,现在索引已更改为2、3、4、1、0。如何在 C 中有效地获取这些索引?提前谢谢(如果可能请写代码)

【问题讨论】:

不是对数组本身进行排序,而是创建一个索引数组并对 that 进行排序,并使用比较器函数来比较索引值。 你能举个例子吗?这对我来说并不完全清楚 好吧,你想让comp(i, j)返回a[i] < a[j](而不是i < j)等等 你能帮我解决这个问题吗?我将用一个例子来澄清。 5,4,1,2,3 是我未排序的数组。现在我得到了一个索引。让我们取第三个索引,第三个索引的值是 2。现在我必须在数组排序后找到值 2 的索引。我该怎么做? 【参考方案1】:

在有限的条件下还有如下方法。

#include <stdio.h>

int main(void)
    int data[] = 5,4,1,2,3 ; //Without duplication, The number of limited range.
    int size = sizeof(data)/sizeof(*data);
    int keys[size];
    int i;

    printf("data :\n");
    for(i=0;i<size;i++)
        printf("%d ",data[i]);
    
    for(i=0;i<size;i++)
        keys[data[i]-1]=i;
    

    printf("\n\ndata\tindex\n");
    for(i=0;i<size;i++)
        printf("%d\t%d\n", data[keys[i]], keys[i]);
    
    return 0;

/* result sample
data :
5 4 1 2 3

data    index
1       2
2       3
3       4
4       1
5       0
*/

建议如何对索引数组@Kerrek 进行排序。

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

int *array;

int cmp(const void *a, const void *b)
    int ia = *(int *)a;
    int ib = *(int *)b;
    return array[ia] < array[ib] ? -1 : array[ia] > array[ib];


int main(void)
    int data[] = 5,4,1,2,3 ;
    int size = sizeof(data)/sizeof(*data);
    int index[size];//use malloc to large size array
    int i;

    for(i=0;i<size;i++)
        index[i] = i;
    
    array = data;
    qsort(index, size, sizeof(*index), cmp);
    printf("\n\ndata\tindex\n");
    for(i=0;i<size;i++)
        printf("%d\t%d\n", data[index[i]], index[i]);
    
    return 0;

【讨论】:

限制是多少?我可以将此方法用于数组中的 10^5 个元素吗?我的整数的最大大小是 10^9。 @user3807678 我认为这可能是Kerrek 之类的一般建议。我已经添加了示例代码。 非常感谢您的代码!我已经获得了一个值的旧索引,我必须在排序数组中找到该值的新索引。我们如何在同一个例子中做到这一点? @user3807678 我不知道你在说什么。你想要i吗? 我会用一个例子来说明。 5,4,1,2,3 是我未排序的数组。现在我得到了一个索引。让我们取第三个索引,第三个索引的值是 2。现在我必须在数组排序后找到值 2 的索引。我该怎么做?【参考方案2】:

获取一个二维数组。将数字存储在第一列,然后将相应的索引存储在第二列。您可以将比较器函数编写为:

int compare ( const void *pa, const void *pb ) 

    const int *a = pa;
    const int *b = pb;
    if(a[0] == b[0])
        return a[1] - b[1];
    else
        return a[0] - b[0];
  

致电qsort 应为:

qsort(array, n, sizeof array[0], compare);  // n is representing rows  

Live Demo

【讨论】:

【参考方案3】:
#include <limits.h>
#include <stdio.h>
#define SIZE 5
int* sortArrayNKeepIndices(int arr[], int arrSize)
    static int indexArr[SIZE];
    int arr2[arrSize];
    for (int i = 0; i < arrSize; i++) 
        indexArr[i] = 0;
        arr2[i] = arr[i];
    
    int min = 0, temp = 0;

    for (int i = 0; i < arrSize ; i++)
    
        min = i;  // record the position of the smallest
        for (int j = i + 1; j < arrSize; j++)
        
            // update min when finding a smaller element
            if (arr[j] < arr[min])
                min = j;
        
        // put the smallest element at position i
        temp = arr[i];
        arr[i] = arr[min];
        arr[min] = temp;
     // array sorting ends here
    int ctr = 0;
    while ( ctr < arrSize) 
        min = 0;  // restart from first element
        for (int j = 0; j < arrSize; j++)
        
            if (arr2[j] == INT_MAX) continue; // ignore already marked as minimum indices
            // update min when finding a smaller element
            if (arr2[j] < arr2[min])
                min = j;
        
        indexArr[ctr] = min; // updating indexArr with the index of the next minimum
        arr2[min] = INT_MAX; // marking minimum element to be ignored next time
        ctr++;
     //keeping track of previous indices of the array elements ends here
    return indexArr;
 // function sortArrayKeepIndices ends here
int main () 
    int arr[SIZE] = 16, 15, 12, 10, 13;
    int* ptr = sortArrayNKeepIndices(arr, SIZE);
    for (int dex = 0; dex < SIZE; dex++)
        printf("%d (%d, %d)\t", arr[dex], * (ptr + dex), dex);

// 输出将是 10 (3, 0) 12 (2, 1) 13 (4, 2) 15 (1, 3) 16 (0, 4) // 元素(旧索引,新索引)

【讨论】:

以上是关于在C中排序后跟踪数组的原始索引的主要内容,如果未能解决你的问题,请参考以下文章

对数组进行排序并保留原始索引

重新排序 UITableView 单元格并跟踪索引

内存高效结构,以原始顺序跟踪数组的子集

排序后如何获取索引排列

使用 numpy 从过滤后的排序数组返回索引

PHP如何跟踪关联数组中的顺序?