gpt4 book ai didi

c++ - 使用索引 vector 重新排序 vector

转载 作者:IT老高 更新时间:2023-10-28 12:39:24 30 4
gpt4 key购买 nike

我想对 vector 中的项目重新排序,使用另一个 vector 来指定顺序:

char   A[]     = { 'a', 'b', 'c' };
size_t ORDER[] = { 1, 0, 2 };

vector<char> vA(A, A + sizeof(A) / sizeof(*A));
vector<size_t> vOrder(ORDER, ORDER + sizeof(ORDER) / sizeof(*ORDER));
<br/>reorder_naive(vA, vOrder);
<br/>// A is now { 'b', 'a', 'c' }

以下是需要复制 vector 的低效实现:

void reorder_naive(vector<char>& vA, const vector<size_t>& vOrder)  
{
assert(vA.size() == vOrder.size());
vector vCopy = vA; // Can we avoid this?
for(int i = 0; i < vOrder.size(); ++i)
vA[i] = vCopy[ vOrder[i] ];
}

有没有更有效的方法,例如使用 swap()?

最佳答案

这个算法是基于chmike的,但是重排序索引的 vector 是const。此功能与他的所有 11 一致! [0..10] 的排列。复杂度是O(N^2),取N作为输入的大小,或者更准确地说,最大的orbit的大小.

关于修改输入的优化 O(N) 解决方案,请参见下文。

template< class T >
void reorder(vector<T> &v, vector<size_t> const &order ) {
for ( int s = 1, d; s < order.size(); ++ s ) {
for ( d = order[s]; d < s; d = order[d] ) ;
if ( d == s ) while ( d = order[d], d != s ) swap( v[s], v[d] );
}
}

这是一个 STL 风格的版本,我投入了更多精力。它快了大约 47%(也就是说,几乎是 [0..10] 的两倍!),因为它尽可能早地完成所有交换,然后返回。重新排序 vector 由多个轨道组成,每个轨道在到达其第一个成员时重新排序。最后几个元素不包含轨道时会更快。

template< typename order_iterator, typename value_iterator >
void reorder( order_iterator order_begin, order_iterator order_end, value_iterator v ) {
typedef typename std::iterator_traits< value_iterator >::value_type value_t;
typedef typename std::iterator_traits< order_iterator >::value_type index_t;
typedef typename std::iterator_traits< order_iterator >::difference_type diff_t;

diff_t remaining = order_end - 1 - order_begin;
for ( index_t s = index_t(), d; remaining > 0; ++ s ) {
for ( d = order_begin[s]; d > s; d = order_begin[d] ) ;
if ( d == s ) {
-- remaining;
value_t temp = v[s];
while ( d = order_begin[d], d != s ) {
swap( temp, v[d] );
-- remaining;
}
v[s] = temp;
}
}
}

最后,为了一劳永逸地回答这个问题,一个确实破坏了重新排序 vector 的变体(用-1填充它)。对于 [0..10] 的排列,它比之前的版本快 16% 左右。因为覆盖输入会启用动态规划,所以它是 O(N),对于某些具有较长序列的情况,渐近更快。

template< typename order_iterator, typename value_iterator >
void reorder_destructive( order_iterator order_begin, order_iterator order_end, value_iterator v ) {
typedef typename std::iterator_traits< value_iterator >::value_type value_t;
typedef typename std::iterator_traits< order_iterator >::value_type index_t;
typedef typename std::iterator_traits< order_iterator >::difference_type diff_t;

diff_t remaining = order_end - 1 - order_begin;
for ( index_t s = index_t(); remaining > 0; ++ s ) {
index_t d = order_begin[s];
if ( d == (diff_t) -1 ) continue;
-- remaining;
value_t temp = v[s];
for ( index_t d2; d != s; d = d2 ) {
swap( temp, v[d] );
swap( order_begin[d], d2 = (diff_t) -1 );
-- remaining;
}
v[s] = temp;
}
}

关于c++ - 使用索引 vector 重新排序 vector ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/838384/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com