对元素进行排序和跟踪

时间:2012-11-06 09:33:15

标签: c++ stl sorting

要知道,我现在正在谈论C ++。

假设我有一个数组A = {4, 1, 5, 2, 3}并在A_sorted = {1, 2, 3, 4, 5}中对其进行排序。我想保留以下信息:现在元素e(来自数组A)在排序数组A_sorted中的位置是什么?例如:A(5)中索引为2的元素现在在A_sorted中具有索引4。

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

6 个答案:

答案 0 :(得分:3)

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

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

然后使用自定义比较器函数对其进行排序,该函数按值而不是原始索引进行排序。

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

答案 1 :(得分:3)

试试这个:  如果你想转换为vector:

 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;
  }

如果你想处理原始数组:

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

  for (int i=0; i<5; i++)
  {      
    int* low = std::lower_bound (&A_sorted[0], &A_sorted[5], A[i]);   
    cout << "Element: " << A[i] << " is at: " << distance(&A_sorted[0], low)  << endl;
  }

答案 2 :(得分:2)

如果您无法修改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);

然后,访问sorted_A[i]作为A[indices[i]],或根据索引重新安排A i -A元素的新位置为std::find(indices, indices+5, i) - indices

答案 3 :(得分:1)

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; 
}

现在对容器ValueWithIndex进行排序。有关原始索引的信息不会 迷路了。

int main()
{
    std::vector<ValueWithIndex<int>> v;
    for(int i = 0; i < n; ++i)
    {
       int value; 
       std::cin >> value;
       v.push_back(MakeValueWithIndex(value, i)); 
    } 

    std::sort(v.begin(), v.end());
}

答案 4 :(得分:1)

好的,索引通常会告诉你向量的第n个排序元素是什么。但是这样做会反过来,因此它会告诉你向量中的第n个元素是按排序顺序的第m个。

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

我们从谓词开始,其中&lt; b如果v [a]&lt; 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中,谓词可以写成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等。

答案 5 :(得分:0)

您可以使用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现在显示相应数组中的索引。