简体   繁体   中英

faster way to sort on value while retaining original index

I'm hoping to get some help coming up with a faster way to do a sort on value while retaining a key on the original order. I would prefer to avoid using boost and it does not need to be a stable sort. This is the code I came up with, it works but is slow and inefficent. I have no need to keep the map after the sort is complete.

struct column_record
{
    int index;
    float value;
};

// sort each column on value while retaining index
column_record *preprocess_matrix(float *value, int m, int n)
{
    std::multimap<float,int> column_map;
    column_record *matrix = new column_record[m*n];

    for (int i=0; i<n; i++)
    {
        for (int j=0; j<m; j++)
        {
            column_map.insert(std::pair<float,int>(value[m*i+j],j));
        }

        int j = 0;

        for (std::multimap<float,int>::iterator it=column_map.begin(); it!=column_map.end(); it++)
        {
            matrix[m*i+j].index = (*it).second;
            matrix[m*i+j].value = (*it).first;
            j++;
        }

        column_map.clear();
    }

    return matrix;
}

Assuming it's fine to return the array of column_record objects, I don't think your solution is particularly inefficient. You could make it cleaner perhaps and eliminate the need for std::multimap by using STL algorithms:

bool compare_column_records(const column_record& lhs, const column_record& rhs)
{
    return lhs.value < rhs.value;
}

column_record* preprocess_matrix(float* value, int m, int n)
{
    const int num_elements = m * n;
    column_record* matrix = new column_record[num_elements];

    for (int i = 0; i < num_elements; ++i)
    {
        // not sure what you mean by index; it looks like you want column index only?
        matrix[i].index = i;
        matrix[i].value = value[i];
    }

    std::sort(matrix, matrix + num_elements, compare_column_records);
    return matrix;
}

First, I see that you use a 1-dimensional array to emulate your matrix. First step, I'd create a new array with the indexes:

int count = m*n;
int *indices = new int[count];
for (i=0;i<count;i++) indices[i] = i;

(I haven't programmed in C++ in a while so I don't know if you can do the initialisation on the fly).

You could then alter a sort method to accept both your original matrix and the newly created indices array and sort on that.

To make things easier, I'd transpose the matrix to sort the rows (consecutive indices), instead of columns.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM