对元素进行排序并跟踪 刚刚知道,我现在在讲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;I
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 );
}
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 ]