对数据结构进行排序并保存原始索引的记录

Sort a data structure and keep record of the original indices

本文关键字:原始 索引 记录 保存 数据结构 排序      更新时间:2023-10-16

假设我有如下代码,用于在另一个数据结构中对数据结构的元素进行排序,但保留其原始索引的记录:

std::vector<int> numbers = {..};
std::vector<std::pair<int, std::vector<int>::size_type>> temp;
for (std::vector<int>::size_type i = 0; i < numbers.size(); i++)
{
    temp.push_back({ numbers[i], i });
}
std::sort(temp.begin(), temp.end(), [](const auto& x, const auto& y) { return x.first < y.first; });

到目前为止一切顺利。但我真正想要的是将数据和索引存储在不同的数据结构中:

std::vector<int> sorted;
std::vector<std::vector<int>::size_type> indices;

使得位于sorted[i]的元素位于原始数据结构的索引indices[i]处。

除了推出我自己的排序算法,或者事后拆分数据结构之外,还有什么简单的技巧可以使用标准库来做到这一点吗?

这个想法是将数据存储在一个容器中,并在其他容器中使用索引(基于不同的排序标准)。

这里的想法是编写函数对象,根据排序标准和数据容器中的值比较两个索引。下一步是将函数对象传递给适当的排序函数。

澄清马太福音的答案…创建一个索引为0到n-1的向量。使用lambda函数根据数据向量对索引向量进行排序。包含可选的重新排序函数的示例代码。

void reorder(std::vector<int>& vA, std::vector<size_t> vI);
int main()
{
    std::vector <int> vdata = { 7,2,4,5,3,1,6,0 };      // original data
    std::vector <size_t> vindex = { 0,1,2,3,4,5,6,7 };  // original indices
    std::sort(vindex.begin(), vindex.end(), [&vdata](size_t i, size_t j)
        {return vdata[i] < vdata[j];});
    for (size_t i = 0; i < vdata.size(); i++)
        std::cout << "[" << vindex[i] << "]=" << vdata[vindex[i]] << " ";
    std::cout << std::endl;
    reorder(vdata, vindex);
    for (size_t i = 0; i < vdata.size(); i++)
        std::cout << "[" << i << "]=" << vdata[i] << " ";
    return 0;
}
// every move places an element in it's final location
// vI passed by value (copy)
void reorder(std::vector<int>& vA, std::vector<size_t> vI)
{
    size_t i, j, k;
    int tA;
    for (i = 0; i < vA.size(); i++) {
        if (i != vI[i]) {
            tA = vA[i];
            k = i;
            while (i != (j = vI[k])) {
                vA[k] = vA[j];
                vI[k] = k;
                k = j;
            }
            vA[k] = tA;
            vI[k] = k;
        }
    }
}