<bdo id='Ktvc5'></bdo><ul id='Ktvc5'></ul>
    1. <i id='Ktvc5'><tr id='Ktvc5'><dt id='Ktvc5'><q id='Ktvc5'><span id='Ktvc5'><b id='Ktvc5'><form id='Ktvc5'><ins id='Ktvc5'></ins><ul id='Ktvc5'></ul><sub id='Ktvc5'></sub></form><legend id='Ktvc5'></legend><bdo id='Ktvc5'><pre id='Ktvc5'><center id='Ktvc5'></center></pre></bdo></b><th id='Ktvc5'></th></span></q></dt></tr></i><div id='Ktvc5'><tfoot id='Ktvc5'></tfoot><dl id='Ktvc5'><fieldset id='Ktvc5'></fieldset></dl></div>
      <tfoot id='Ktvc5'></tfoot>
    2. <legend id='Ktvc5'><style id='Ktvc5'><dir id='Ktvc5'><q id='Ktvc5'></q></dir></style></legend>
      1. <small id='Ktvc5'></small><noframes id='Ktvc5'>

        使用索引向量重新排序向量

        时间:2023-09-16

            <bdo id='xCZOq'></bdo><ul id='xCZOq'></ul>
              <tbody id='xCZOq'></tbody>
          • <legend id='xCZOq'><style id='xCZOq'><dir id='xCZOq'><q id='xCZOq'></q></dir></style></legend>

            <tfoot id='xCZOq'></tfoot>
              1. <small id='xCZOq'></small><noframes id='xCZOq'>

                <i id='xCZOq'><tr id='xCZOq'><dt id='xCZOq'><q id='xCZOq'><span id='xCZOq'><b id='xCZOq'><form id='xCZOq'><ins id='xCZOq'></ins><ul id='xCZOq'></ul><sub id='xCZOq'></sub></form><legend id='xCZOq'></legend><bdo id='xCZOq'><pre id='xCZOq'><center id='xCZOq'></center></pre></bdo></b><th id='xCZOq'></th></span></q></dt></tr></i><div id='xCZOq'><tfoot id='xCZOq'></tfoot><dl id='xCZOq'><fieldset id='xCZOq'></fieldset></dl></div>

                  本文介绍了使用索引向量重新排序向量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

                  问题描述

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

                  I'd like to reorder the items in a vector, using another vector to specify the order:

                  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));
                  
                  reorder_naive(vA, vOrder);
                  // A is now { 'b', 'a', 'c' }

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

                  The following is an inefficient implementation that requires copying the 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()?

                  Is there a more efficient way, for example, that uses swap()?

                  推荐答案

                  该算法基于 chmike 的,但重新排序索引的向量是 const.这个功能都同意他的11![0..10] 的排列.复杂度为 O(N^2),取 N 作为输入的大小,或者更准确地说,最大的大小 轨道.

                  This algorithm is based on chmike's, but the vector of reorder indices is const. This function agrees with his for all 11! permutations of [0..10]. The complexity is O(N^2), taking N as the size of the input, or more precisely, the size of the largest orbit.

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

                  See below for an optimized O(N) solution which modifies the input.

                  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] 的两倍!)因为它尽可能早地完成所有交换然后返回.重新排序向量由许多轨道组成,每个轨道在到达其第一个成员时重新排序.当最后几个元素不包含轨道时,速度会更快.

                  Here's an STL style version which I put a bit more effort into. It's about 47% faster (that is, almost twice as fast over [0..10]!) because it does all the swaps as early as possible and then returns. The reorder vector consists of a number of orbits, and each orbit is reordered upon reaching its first member. It's faster when the last few elements do not contain an orbit.

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


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


                  And finally, just to answer the question once and for all, a variant which does destroy the reorder vector (filling it with -1's). For permutations of [0..10], It's about 16% faster than the preceding version. Because overwriting the input enables dynamic programming, it is O(N), asymptotically faster for some cases with longer sequences.

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

                  这篇关于使用索引向量重新排序向量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持html5模板网!

                  上一篇:将元素从 std::vector 移动到另一个 下一篇:std::vector、默认构造、C++11 和重大更改

                  相关文章

                  最新文章

                  <small id='DeTYt'></small><noframes id='DeTYt'>

                • <i id='DeTYt'><tr id='DeTYt'><dt id='DeTYt'><q id='DeTYt'><span id='DeTYt'><b id='DeTYt'><form id='DeTYt'><ins id='DeTYt'></ins><ul id='DeTYt'></ul><sub id='DeTYt'></sub></form><legend id='DeTYt'></legend><bdo id='DeTYt'><pre id='DeTYt'><center id='DeTYt'></center></pre></bdo></b><th id='DeTYt'></th></span></q></dt></tr></i><div id='DeTYt'><tfoot id='DeTYt'></tfoot><dl id='DeTYt'><fieldset id='DeTYt'></fieldset></dl></div>
                    <legend id='DeTYt'><style id='DeTYt'><dir id='DeTYt'><q id='DeTYt'></q></dir></style></legend>
                  1. <tfoot id='DeTYt'></tfoot>
                    • <bdo id='DeTYt'></bdo><ul id='DeTYt'></ul>