【问题标题】:Reorder vector according to a vector of indices - update根据索引向量重新排序向量 - 更新
【发布时间】:2014-03-06 08:15:12
【问题描述】:

这是对previous question about reordering in place 的更新。关于索引向量存在一些混淆。调用要重新排序的向量 vA,以及索引向量 vI,然后 vA 应按此顺序重新排序,vA[vI[0]],vA[vI[1]],vA[vI[2],... .一个示例用法是将 vI 初始化为一组 vA.size() 索引,从 0 到 vA.size()-1,然后根据 vA 对 vI 进行排序(使用 vA[vI[...]] 进行比较)。然后可以使用 reorder 函数对 vA 根据 vI 进行排序。

将初始 vA 视为已排序 vA 的排列。在根据 vA 对 vI 进行排序之后,然后根据 vI 对 vA 重新排序“取消排列” vA 回到排序后的排列。使用下面显示的示例函数,重新排序 vA 也会将 vI 重新排序回其初始化状态(0 到 vA.size()-1)。

【问题讨论】:

  • 我认为您正在尝试执行“收集”功能。如果你想要它已经在 boost 库中实现 (boost/algorithm/gather.hpp) boost.org/doc/libs/1_41_0/doc/html/boost/mpi/gather.html
  • 这里的目标是重新排序。制作有序副本很容易: for(i = 0; i
  • 我更新了这个问题,加入了上一个问题的链接。

标签: c++ sorting vector


【解决方案1】:

下面的示例显示了一个名为 reorderfail() 的非工作版本的重新排序,然后是一个名为 reorder() 的工作版本。这两个函数都将 vI 返回到其原始状态 0 到 vA.size()-1,但 reorderfail() 无法正确重新排序 vA,因为它缺少“取消置换”vA 所需的间接级别。

#include <algorithm>
#include <vector>

using namespace std;

template <class T>
void reorderfail(vector<T>& vA, vector<size_t>& vI)  
{   
size_t i, j;
    for(i = 0; i < vA.size(); i++ ){ 
        while(i != (j = vI[i])){
            swap(vA[i], vA[j]);
            swap(vI[i], vI[j]);
        }
    }
}

template <class T>
void reorder(vector<T>& vA, vector<size_t>& vI)  
{
size_t i, j, k;
    for(i = 0; i < vA.size(); i++){ 
        while(i != (j = vI[i])){
            k = vI[j];
            swap(vA[j], vA[k]);
            swap(vI[i], vI[j]);
        }
    }
}

int main( )
{
char A[]   = { 'b', 'c', 'a' };
size_t I[] = {  2 ,  0 ,  1  };  // order should be A[2] A[0] A[1]
size_t size = sizeof(A) / sizeof(*A);

    vector<char>   vA(size);
    vector<size_t> vI(size);

    vA.assign(A, A + size);
    vI.assign(I, I + size);
    reorderfail(vA, vI);    // returns vA = {'c', 'a', 'b'};

    vA.assign(A, A + size);
    vI.assign(I, I + size);
    reorder(vA, vI);        // returns vA = {'a', 'b', 'c'};

    return(0);
}

【讨论】:

    【解决方案2】:

    移动数据而不是交换数据的工作重排序版本。这个例子可能更容易解释。每个排列都是一组“循环”。通过撤消循环来重新排序。假设有 8 个元素,并且 vI 包含所需的顺序。我把索引 i 放在了 vi 上面:

    i :     {  0 ,  1 ,  2 ,  3 ,  4 ,  5 ,  6 ,  7  }
    
    vI[i] = {  5 ,  7 ,  0 ,  3 ,  6 ,  2 ,  4 ,  1  }
    

    循环 1:vI[0] == 5,vI[5] == 2,vI[2] == 0。

    循环 2:vi[1] == 7,vi[7] == 1。

    循环 3:vI[3] == 3。

    循环 4:vI[4] == 6,vi[6] == 4。

    撤销循环1,t = vA[0],vA[0] = vA[5],vA[5] = vA[2],vA[2] = t。

    撤销循环2,t = vA[1],vA[1] = vA[7],vA[7] = t。

    撤消循环 3,无需更正

    撤销循环4,t = vA[4],vA[4] = vA[6],vA[6] = t。

    每次在 vA[k] 中存储一个值时,vI[k] 被设置为 k,表示 vA[k] 是有序的。

    template <class T>
    void reorder(vector<T>& vA, vector<size_t>& vI)  
    {
    size_t i, j, k;
    T t;
        for(i = 0; i < vA.size(); i++){
            if(i != vI[i]){
                t = vA[i];
                k = i;
                while(i != (j = vI[k])){
                // every move places a value in it's final location
                    vA[k] = vA[j];
                    vI[k] = k;
                    k = j;
                }
                vA[k] = t;
                vI[k] = k;
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2018-06-21
      • 2010-10-24
      • 2021-09-22
      • 1970-01-01
      • 2014-11-13
      • 2015-09-01
      • 1970-01-01
      • 2021-12-23
      • 2019-12-14
      相关资源
      最近更新 更多