对元素进行排序并跟踪 刚刚知道,我现在在讲C++。< /P>

对元素进行排序并跟踪 刚刚知道,我现在在讲C++。< /P>,c++,stl,sorting,C++,Stl,Sorting,假设我有一个数组A={4,1,5,2,3},并在A_sorted={1,2,3,4,5}中对其排序。我想保留以下信息:已排序数组A中的元素e(来自数组A)现在在哪里?e、 g.(5)中有索引2的元素现在在A_中有索引4 问题更像是:可以使用STL来实现这一点吗?没有现成的功能来实现这一点,但有一些解决方法。例如,您可以保留一个用户定义的结构数组,其中也包含原始位置: template<class T> struct ValueWithIndex { T Value;

假设我有一个数组
A={4,1,5,2,3}
,并在
A_sorted={1,2,3,4,5}
中对其排序。我想保留以下信息:已排序数组A中的元素
e
(来自数组A)现在在哪里?e、 g.(
5
)中有索引2的元素现在在A_中有索引4


问题更像是:可以使用STL来实现这一点吗?

没有现成的功能来实现这一点,但有一些解决方法。例如,您可以保留一个用户定义的结构数组,其中也包含原始位置:

template<class T>
struct ValueWithIndex
{
    T Value;
    int index;
};
template<class T>
bool operator < (const ValueWithIndex<T>& v1, const ValueWithIndex<T>& v2)
{
    return v1.value < v2.value;
}
template<class T> ValueWithIndex<T>
MakeValueWithIndex(const T& value, int index)
{
    ValueWithIndex<T> ret;
    ret.value = value;
    ret.index = index;
    return ret; 
}
A = { {4,0}, {1,1}, {5,2}, {2,3}, {3,4}}
然后使用自定义比较器函数对其进行排序,该函数按值而不是原始索引进行排序

A_sorted = {{1,1}, {2,3}, {3,4}, {4,0}, {5,2}}

您可以使用
find
搜索元素:

int *p1 = std::find(&A[0], &A[5], 5);
int *p2 = std::find(&A_sorted[0], &A_sorted[5], 5);
并使用距离来显示索引:

int i1 = p1 - A;
int i2 = p2 - A_sorted;
i1和i2现在显示相应数组中的索引。

请尝试以下操作: 如果要转换为矢量,请执行以下操作:

 int A[] = {4, 1, 5, 2, 3};
 int A_sorted [] = {1, 2, 3, 4, 5};
 std::vector<int> v(A_sorted, A_sorted + 5);  

  for (int i=0; i<5; i++)
  {          
    std::vector<int>::iterator low = lower_bound (v.begin(), v.end(), A[i]);   
    std::cout << "Element: " << A[i] << " is at: " << distance(v.begin(), low)  << std::endl;
  }
inta[]={4,1,5,2,3};
int A_排序[]={1,2,3,4,5};
向量v(A_排序,A_排序+5);

对于(int i=0;i如果无法修改
A
中存储的内容,可以创建索引数组并使用特殊谓词对其排序:

int A[] = {4, 1, 5, 2, 3};

size_t indices[] = {0, 1, 2, 3, 4};

bool sortBefore(size_t i, size_t j) {
  return A[i] < A[j];
}

std::sort(indices, indices + 5, sortBefore);
inta[]={4,1,5,2,3};
大小指数[]={0,1,2,3,4};
bool排序前(尺寸i,尺寸j){
返回A[i]

然后,将
排序的A[i]
访问为
A[index[i]
,或者根据索引重新排列
A
。A
的第i个元素的新位置是
std::find(index,index+5,i)-索引

好的,索引通常会告诉您向量的第n个排序元素是什么。但这会做相反的事情,因此它会告诉您向量中的第n个元素是按排序顺序排列的第m个元素

这是通过在未排序的向量上创建索引向量来实现的。当然,您仍然可以创建排序副本或索引

我们从一个谓词开始,如果v[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 );
}
}

现在,我们的转置索引为您提供了所需的内容,转置本身是
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等。

我不确定这是否回答了问题。这是如何创建索引以查找原始集合中的位置,但我认为他要求查找项目在索引中的集合位置。是的,这会起作用,将为每个项目设置O(logN)以找到其位置。为什么为O(logN)?下限
是否知道数组已排序?在我看来,这是最快的解决方案,因为它是唯一不会增加比较次数的解决方案。这是否正确?那么,在原始数组中给定位置2,如何找到值5(5)的位置在没有完全扫描的已排序副本中?我建议在排序后扫描一次,用A_的实际索引更新A_的副本:for(int I=0;Itemplate< 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 ); }
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;
   }
 [ _, _, _, _, _ ]
 [ _, _, _, _, 0 ]
 [ _, 1, _, _, 0 ]
 [ 2, 1, _, _, 0 ]
 [ 2, 1, _, 3, 0 ]
 [ 2, 1, 4, 3, 0 ]