这是对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)。
答案 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;
}
}
}