根据索引向量重新排序向量 - 更新

时间:2014-03-06 08:15:13

标签: c++ sorting vector

这是对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 [...]]进行比较)。然后可以使用重新排序功能根据vI对vA进行排序。

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

2 个答案:

答案 0 :(得分:0)

下面的示例显示了一个名为reorderfail()的重新排序的非工作版本,后跟一个名为reorder()的工作版本。这两个函数都将vI返回到原始状态0到vA.size() - 1,但是reorderfail()无法正确重新排序vA,因为它缺少“unpermute”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);
}

答案 1 :(得分:0)

工作重新排序的一个版本,用于移动数据而不是交换数据。这个例子可能更容易解释。每个排列都是一组&#34;周期&#34;。重新排序通过撤消循环来工作。假设有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;
        }
    }
}