c++ - 按特定顺序排列向量元素

Posted

技术标签:

【中文标题】c++ - 按特定顺序排列向量元素【英文标题】:c++ - Arranging vector elements in a specific order 【发布时间】:2013-10-19 14:43:13 【问题描述】:

我正在开始编程,很抱歉我缺乏知识。 如何按特定顺序设置向量中的元素?我想以彼此之间不会有相同元素的方式交换元素。 例如向量包含:

1, 2, 2, 2, 3, 3, 4, 4, 4

我希望它是这样的:

1, 2, 4, 3, 4, 2, 3, 2, 4

感谢您的帮助。

编辑: 再次您好,我没有找到最好的解决方案,也许您可​​以看看并纠正它?

   map<unsigned,unsigned> Map;
   for(vector<unsigned>::iterator i=V.begin();i!=V.end();++i)
     
      map<unsigned,unsigned>::iterator f=Map.find(*i);
      if(f==Map.end()) Map[*i]=1;
      else ++f->second;
     
   for(bool more=true;more;)
     
      more=false;
      for(map<unsigned,unsigned>::iterator i=Map.begin();i!=Map.end();++i)
        
         if(i->second)
           
            --i->second;
            cout<<i->first<<", ";
            more=true;
           
                    
     

现在,对于 1, 2, 2, 2, 3, 3, 4, 4, 4, 4, 4, 4 它给了我 1, 2, 3, 4, 2, 3, 4, 2 , 4, 4, 4, 4 而不是例如 4, 1, 4, 2, 4, 3, 4, 2, 4, 3, 4, 2 。如何做呢?谢谢

学分:_13th_Dragon

【问题讨论】:

如果这是不可能的怎么办?取决于你想要什么,尽管std::unique 可能会有所帮助。 Algorithm to separate items of the same type的可能重复 你必须开发一个算法来做到这一点。然后你应该关心实现它。乍一看,这似乎不是一个简单的问题。 @chris,谢谢,但我看不出它对我有什么帮助。如果这种“排序”是不可能的,它可以返回 0 或任何其他信息,向量将不再被使用.也许您知道一种随机化元素(包括我的条件)的算法? :) 有很多解决方案。还有其他要求吗? 【参考方案1】:
    计算每个值的出现次数。 从最频繁的值开始,交替使用不太频繁的值。

为了实现(1),可以简单地使用std::map&lt;V, unsigned&gt;。但是,对于第二个,需要一组有序的std::pair&lt;V, unsigned int&gt;,按第二个值排序。由于我们想要跟踪我们需要使用给定值的次数,因此第二个值不能是恒定的。此外,如果我们碰巧大大减少了给定值的计数,我们也不想更改顺序。总而言之,我们得到了

#include <iostream>
#include <vector>
#include <algorithm>
#include <map>

// In the pair, first is the original value, while 
// second is the number occurrences of that value.
typedef std::pair<int, unsigned> value_counter;

int main()
  std::vector<int> sequence =  0, 1, 3, 3, 4, 1, 2, 2, 2, 2 , 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4 ;
  std::map<int, unsigned> count;

  for( auto i : sequence)
    count[i]++;
  

  std::vector<value_counter> store( count.size() );
  std::copy(count.begin(), count.end(), store.begin());

  // Sort by the second value
  std::sort(store.begin(), store.end(), 
    [](const value_counter& a, const value_counter& b)
      return a.second > b.second;
  );

  std::vector<int> result;

  // We need two indices, one for the current value
  // and the other one for the alternative
  for(unsigned i = 0, j = 1; i < store.size(); ++i)
    while(store[i].second > 0)
      result.push_back(store[i].first);
      store[i].second--;
      if(store[i].second == 0)
        continue;

      if( j <= i)
        j = i + 1;
      while(j < store.size() && store[j].second == 0)
        ++j;
      if(j >= store.size())
        std::cerr << "Not enough elements for filling!" << std::endl;
        return 1;
      
      else 
        result.push_back(store[j].first);
        store[j].second--;
      
    
  

  for( auto r : result)
    std::cout << r << " ";
  

您可以创建一个替代计数器,而不是使用 typedef,该计数器的名称比 firstsecond 更好,但这会使从地图复制更加冗长。

【讨论】:

谢谢!目前,这是我找到的最佳解决方案。再次感谢你:) @pablo7890:如果您对算法的复杂性感兴趣:它应该是 O(n log k),其中 k 是不同值的数量。 谢谢。它可能对我有用。我还有一个问题,以前我认为我不必指定第一个和最后一个元素。它可以在您的算法中实现吗?我可能知道如何添加第一个元素:在定义向量 结果之后只是 push_back (first_element) 并从 1 而不是从 0 开始循环,但我完全不知道如何让它添加最后一个元素,所以最后一个一个和以前的不一样.. 等等,最后一个不能匹配第一个?那不应该发生。发生这种情况的唯一方法是,一个值出现 n 次,并且整个事物的长度为 2n - 1。如果发生这种情况,您将无能为力。否则,算法应该防止这种情况发生。 好吧,也许我应该举一个例子,我正在尝试做什么,因为我不知道我是否理解正确(英语不是我的首要语言)。向量是 1, 1, 2, 2, 2, 3, 3, 3 和 First = 3;最后 = 1;所以输出可能是 3, 2, 1, 3, 2, 3, 2, 1 。你知道怎么做吗?我正在网上寻找解决方案,恐怕没有简单的算法。谢谢!

以上是关于c++ - 按特定顺序排列向量元素的主要内容,如果未能解决你的问题,请参考以下文章

c++中向量中的元素除法

C ++中动态分配的向量中的分段错误

如何将upper_bound与成对向量一起使用,按pair.second的递增顺序排列,然后pair.first?

在 C++ 中并行查找向量的第一个

我如何按类属性对C++向量数组进行排序[重复]

C ++按字母顺序对结构向量进行排序