好的,索引通常会告诉您向量的第 n 个排序元素是什么。但这会反过来,因此它会告诉您向量中的第 n 个元素是排序顺序中的第 m 个。
这是通过在未排序的向量上创建索引向量来完成的。当然,您仍然可以创建排序副本或索引。
我们从一个谓词开始,它的 a
template< typename T >
class PredByIndex
{
private:
std::vector< T > const & theColl;
public:
PredByIndex( std::vector<T> const& coll ) : theColl( coll )
{
}
bool operator()( size_t i, size_t j ) const
{
return theColl[i] < theColl[j];
}
};
template< typename T >
void makeOrdered( std::vector< T > const& input, std::vector< size_t > & order )
{
order.clear();
size_t len = input.size();
order.reserve( len );
for( size_t i = 0; i < len; ++i )
{
order.push_back( i );
}
PredByIndex<T> pred( input );
std::sort( order.begin(), order.end(), pred );
}
现在“order”将在有序集合中具有序数位置。
当然,在 C++11 中,谓词可以写成 lambda 表达式,而不必创建类 PredByIndex。
我们还没有完成。我们现在有一个索引,而不是“在排序向量中找到我”。但是我们可以transpose我们的索引如下:
void transpose_index( std::vector< size_t > const & index,
std::vector< size_t > & trans )
{
// for this to work, index must contain each value from 0 to N-1 exactly once.
size_t size = index.size();
trans.resize( index.size() );
for( size_t i = 0; i < size; ++i )
{
assert( index[i] < size );
// for further assert, you could initialize all values of trans to size
// then as we go along, ensure they still hold that value before
// assigning
trans[ index[i] ] = i;
}
}
现在我们的转置索引给了你想要的,转置本身就是O(N)
在一个稍微不同的数据示例中,如果输入是[ 5, 3, 11, 7, 2 ]
“排序”顺序是[ 2, 3, 5, 7, 11 ]
“索引”顺序是[4, 1, 0, 3, 2],即元素 4 最小,然后是元素 1,依此类推。
我们填写的“转置”顺序
[ _, _, _, _, _ ]
[ _, _, _, _, 0 ]
[ _, 1, _, _, 0 ]
[ 2, 1, _, _, 0 ]
[ 2, 1, _, 3, 0 ]
[ 2, 1, 4, 3, 0 ]
这看起来像我们想要的。我们的原始数据5是位置2,3是位置1,11是位置4等等。