什么数据结构更适合用于存储和排序<int,int =“”>结构?</int,>

时间:2013-02-12 10:44:50

标签: c++ sorting data-structures

我有这样的结构,带有ID及其数量:

product[38] = 10;
product[22] = 7;
product[39] = 18;

我需要使用一些结构。但不确定应该更好地提供什么(mapunordered_mapsetvector)。

我试图使用:

map<int, int> product;

但不确定它是最好的选择。我应该做的唯一一件事 - 排序。

因此我需要:

product[39] = 18;
product[38] = 10;
product[22] = 7;

UPD:按值排序。

5 个答案:

答案 0 :(得分:5)

你可能想要制作一个结构或std::pair并在std::vector

中将它们弄干
std::vector<std::pair<int, int>> product;

product.push_back(std::pair<int,int>(38, 27));
product.push_back(std::pair<int,int>(22, 7));
product.push_back(std::pair<int,int>(39, 18));

按值排序:

std::sort(product.begin(), product.end(), 
  [](const std::pair<int,int>& p1, const std::pair<int,int>& p2){ return p1.second < p2.second; });

答案 1 :(得分:4)

在这种情况下,std::map很好,因为您正在将ID映射到计数。

供将来参考:

enter image description here

答案 2 :(得分:1)

如果我必须在你提出的用法的范围内做这个(保持快速计数器更新的键映射,然后转储排序结果),我可能会使用无序映射和指针向量。有了这个,我假设你首先想要一些索引键解决方案的主要原因是在更新计数时使数据处理速度明显加快。

换句话说,您希望通过以下代码获得良好的速度提升:

++product[ id ]; // increment counter for product 'id' in our keyed-container.

但仍然能够报告不是在id上排序的输出,而是报告每个id的累计计数。话虽如此,以下虽然有点密集,但完全

#include <iostream>
#include <sstream>
#include <algorithm>
#include <vector>
#include <ctime>
#include <unordered_map>
#include <iterator>
#include <iomanip>
using namespace std;

int main(int argc, char *argv[])
{
    typedef std::unordered_map<int, int> Products;
    Products product;

    // fill with random data for our test.
    std::srand((unsigned)time(0));
    for (int i=1;i<20;++i)
    {
        product[i] = rand() % 50 + 1;
        cout << setw(3) << i << " ==> " << product[i] << endl;
    }
    cout << endl;


    // now setup a one-shot sort. we're using a vector of
    //  pointers to our map value type
    std::vector<const Products::value_type*> data;
    data.reserve(product.size());
    std::transform(product.begin(), product.end(), std::back_inserter(data),
                   [](const Products::value_type& obj) { return std::addressof(obj); });

    // sort the vector by value (second)
    std::stable_sort(data.begin(), data.end(),
                     [](const Products::value_type* left, const Products::value_type* right)
                     { return left->second < right->second; });

    // results are in the vector as pointers. the original map is unchanged.
    for (auto ptr : data)
        cout << setw(3) << ptr->first << " ==> " << ptr->second << endl;

    return EXIT_SUCCESS;
};

示例运行

  1 ==> 42
  2 ==> 18
  3 ==> 35
  4 ==> 1
  5 ==> 20
  6 ==> 25
  7 ==> 29
  8 ==> 9
  9 ==> 13
 10 ==> 15
 11 ==> 6
 12 ==> 46
 13 ==> 32
 14 ==> 28
 15 ==> 12
 16 ==> 42
 17 ==> 46
 18 ==> 43
 19 ==> 28
 20 ==> 37

  4 ==> 1
 11 ==> 6
  8 ==> 9
 15 ==> 12
  9 ==> 13
 10 ==> 15
  2 ==> 18
  5 ==> 20
  6 ==> 25
 14 ==> 28
 19 ==> 28
  7 ==> 29
 13 ==> 32
  3 ==> 35
 20 ==> 37
  1 ==> 42
 16 ==> 42
 18 ==> 43
 12 ==> 46
 17 ==> 46

我过去曾经使用过这种方法,因为对于更复杂的结构来说,这种方法非常有效,复制到临时容器进行分类是很昂贵的。结束指针向量引用地图中的真实数据是一个非常精确的问题,虽然对于这个特定问题可能有点过分,但作为一般解决方案肯定会获得好处。

话虽如此,如果你想要的只是一个int-to-int转储,在second-int而不是你的map键上排序,这同样可以解决问题,尽管它确实会从你的容器中复制数据来完成最终目标是:

#include <iostream>
#include <sstream>
#include <algorithm>
#include <vector>
#include <ctime>
#include <unordered_map>
#include <iterator>
#include <iomanip>
using namespace std;

int main(int argc, char *argv[])
{
    typedef std::unordered_map<int, int> Products;
    Products product;

    // fill with random data for our test.
    std::srand((unsigned)time(0));
    for (int i=1;i<20;++i)
    {
        product[i] = rand() % 50 + 1;
        cout << setw(3) << i << " ==> " << product[i] << endl;
    }
    cout << endl;

    // copy the values from the map to a sort bed.
    std::vector<std::pair<int,int>> vals;
    std::copy(product.begin(), product.end(), back_inserter(vals));
    std::stable_sort(vals.begin(), vals.end(),
        [](const std::pair<int,int>& left, const std::pair<int,int>& right)
        { return left.second < right.second; });

    // dump to stdout
    for (auto val : vals)
        cout << setw(3) << val.first << " ==> " << val.second << endl;

    return EXIT_SUCCESS;
}

示例输出

  1 ==> 48
  2 ==> 30
  3 ==> 25
  4 ==> 32
  5 ==> 34
  6 ==> 21
  7 ==> 26
  8 ==> 6
  9 ==> 50
 10 ==> 28
 11 ==> 50
 12 ==> 32
 13 ==> 35
 14 ==> 17
 15 ==> 33
 16 ==> 30
 17 ==> 13
 18 ==> 1
 19 ==> 50

 18 ==> 1
  8 ==> 6
 17 ==> 13
 14 ==> 17
  6 ==> 21
  3 ==> 25
  7 ==> 26
 10 ==> 28
  2 ==> 30
 16 ==> 30
  4 ==> 32
 12 ==> 32
 15 ==> 33
  5 ==> 34
 13 ==> 35
  1 ==> 48
  9 ==> 50
 11 ==> 50
 19 ==> 50

答案 3 :(得分:1)

我通常按以下方式做:

创建两个int成员的类/结构

struct int_pair{
     int key;
     int value;
}

然后创建一个

   vector<int_pair> myvector;

然后创建两个bool比较函数:

 bool sort_by_key(int_pair left, int_pair right){
      return left.key<right.key;
 }

 bool sort_by_value(int_pair left, int_pair right){
     return left.value<right.value;
 }

然后使用std :: sort和那些bool函数进行排序。

 std::sort (myvector.begin(), myvector.end(), sort_by_key); 

p.s:抱歉格式化。从手机输入。

答案 4 :(得分:0)

您只需使用boost.bimap即可。它是一个很容易理解它的工作,但它的价值,我认为它完全适合你的用例。