【问题标题】:Selectively sort vector c++选择性排序向量c ++
【发布时间】:2017-06-09 07:50:03
【问题描述】:

我有以下向量:

vector<unsigned> vec = {5, 6, 5, 4, 1, 3, 0, 4}

现在我想按字典顺序按奇数索引对这个向量进行排序(如果奇数索引相等,则按偶数索引)。这样排序后的向量“vec”就是:

   {0, 4, 1, 3, 5, 4, 5, 6}

我知道 std::sort 将完全对“vec”进行排序。是否可以使用 std::sort 有选择地对向量进行排序。对于 std::lower_bound 也是如此。是否可以仅使用奇数索引找到 lower_bound。

我想要与对向量相同的效果。出于效率原因,我没有将 vec 存储为对的向量。

【问题讨论】:

  • 不太清楚你想如何排序。比如原向量中的6怎么了?
  • 据我了解,您需要一对向量,并对它们进行排序(并将向量展平)。
  • 您可以编写自己的迭代器,这样当它递增时,它会返回下一个偶数索引;但就我个人而言,我怀疑尝试仅对集合中的偶数进行排序,意味着数据没有很好地表示
  • std::pair 效率低怎么办?
  • 类型不仅用于保存数据,还用于表达您想要对这些数据执行的操作。如果你想对一个向量对进行排序,那么vector&lt;unsigned&gt; 是错误的类型

标签: c++ sorting c++11 vector


【解决方案1】:

效率不高,但可行的解决方案是:

std::vector<std::pair<size_t,unsigned int>> temp_vec;
temp_vec.reserve(vec.size());
for(size_t i=0;i<vec.size();++i){
    temp_vec.emplace_back(i,vec[i]);
}
std::sort(temp_vec.begin(),temp_vec.end(),[](auto l,auto r){
    return /* some condition based on l.first and r.first*/;
});
std::transfrom(temp_vec.begin(),temp_vec.end(),vec.begin(),[](auto item){
     return item.second;
});

【讨论】:

    【解决方案2】:

    这可以通过使用自定义迭代器调用std::sort 来实现,该迭代器跳过索引和自定义比较函数,如果当前比较相等,则比较相邻值。

    自定义迭代器可以构建在现有迭代器之上。像这样的构造称为迭代器适配器。你不需要自己从头开始编写这样的迭代器适配器,因为 boost 已经完成了艰苦的工作。您可以使用boost::adaptors::strided。如果你不能使用 boost,那么你可以重新实现它。


    不过,更简单的解决方案是使用对。或者更好的是,如果成员有合理的名称,则为结构。

    【讨论】:

      【解决方案3】:

      使用range-v3,您可以这样做:

      std::vector<unsigned> vec = {5, 6, 5, 4, 1, 3, 0, 4};
      auto pair_view = ranges::view::zip(vec | ranges::view::stride(2),
                                         vec | ranges::view::drop(1) |  ranges::view::stride(2));
      
      ranges::sort(pair_view);
      

      Demo

      【讨论】:

      • 简单优雅! ... :-)
      • 请注意,这可以手动完成,也可以通过 boost 完成,这可能会帮助那些还不想使用 C++20 的人。 ;)
      【解决方案4】:

      不是最快的排序算法,但它有效:

      #include <vector>
      #include <algorithm>
      
      int main()
      {
          std::vector<unsigned> vec = { 5, 6, 5, 4, 1, 3, 0, 4 };
      
          if (vec.size() > 1 && vec.size() % 2 == 0)
          {
              for (size_t i1 = 0, j1 = i1 + 1; i1 < vec.size() - 1 && j1 < vec.size(); i1+=2, j1 = i1+1)
              { 
                  for (size_t i2 = i1 + 2, j2 = i2 + 1; i2 < vec.size() - 1 && j2 < vec.size(); i2 += 2, j2 = i2 + 1)
                  {
                      if (vec[i1] > vec[i2] || (vec[i1] == vec[i2] && vec[j1] > vec[j2]))
                      {
                          std::swap(vec[i1], vec[i2]);
                          std::swap(vec[j1], vec[j2]);
                      }
                  }
              }
          }
          return 0;
      }
      

      [On Coliru]

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-03-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-20
        相关资源
        最近更新 更多