わかりました、インデックスは通常、ベクトルの n 番目に並べ替えられた要素が何であるかを示します。しかし、これは逆になるため、ベクトルの n 番目の要素がソート順で m 番目であることがわかります。
これは、ソートされていないベクトルにインデックスのベクトルを作成することによって行われています。もちろん、ソートされたコピーやインデックスを作成することもできます。
a < b if v[a] < v[b] の述語から始めます。
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 );
}
そして今、「注文」は、注文されたコレクション内で序数の位置を持ちます。
もちろん、C++11 では 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などです。