C ++中带散列/矢量映射的自动聚类

时间:2010-01-07 06:59:27

标签: c++ data-structures hash map vector

我有以下值,例如:

0 0 0 1 3 2

这些值是指群集ID,其中群集的成员是 向量的索引。因此我们希望获得这种输出:

Cluster 0 -> 0,1,2
Cluster 1 -> 3
Cluster 2 -> 5
Cluster 3 -> 4

我尝试了以下构造但它似乎不起作用: 有什么办法呢?

#include <iostream>      
#include <vector>        
#include <fstream>
#include <sstream>
#include <map>
using namespace std;

int main  ( int arg_count, char *arg_vec[] ) {
    if (arg_count !=2 ) {
        cerr << "expected one argument" << endl;
        return EXIT_FAILURE;      
    }

    string line;
    ifstream myfile (arg_vec[1]);

    map <int, vector <int> > CCTagMap;

    if (myfile.is_open())
    {
        // Skip First Line        
        getline(myfile,line);     

        while (getline(myfile,line) )
        {
            stringstream ss(line);    
            int CcId;
            int TagId = -1;           



            vector <int> Temp;        

            while (ss >> CcId) {      
                TagId++;
                cout << CcId << "-" << TagId <<  endl; 

                # this way to cluster doesn't seem to work
                CCTagMap.insert(make_pair(CcId,Temp.push_back(TagId)));
            }


        }
        myfile.close();
    }
    else  { cout << "Unable to open file\n";} 
    return 0;
}

4 个答案:

答案 0 :(得分:2)

每次插入时都会覆盖矢量。你可以做的是:

map <int, vector <int> >::iterator iter = CCTagMap.find(CcId);
if(iter == CCTagMap.end())
{
  vector <int> Temp;  
  temp.push_back(TagId);
  CCTagMap[CcId] = temp;
}
else
{
  iter->second.push_back(TagId);
}

答案 1 :(得分:2)

我想我会发布一个针对性能的解决方案(记住,你应该总是尝试根据Knuth尽快优化!除非我弄错了;)。)。

CCTagMap[CcId].push_back(TagId);

是的,我真的认为我应该指出这个解决方案......

  • 保存一些打字
  • 性能更高:只有一个查找,而不是一个用于查找,一个用于插入。没有临时性(尽管它们可能会进行优化)。
  • 惯用?

对于此处发生的事情的分解视图:

std::vector<int>& CcVector = CcTagMap[CcId]; // [1]
CcVector.push_back(TagId);                   // [2]
  1. map::operator[]是一个变异运算符:它返回为此键存储的元素,或者如果不存在则插入新的默认构造元素。然后它返回对元素的引用(无论是否为新)。
  2. 我们使用直接push_back的引用,很好,干净。

答案 2 :(得分:1)

你做错了是每次都在地图中重写矢量。

而不是:

CCTagMap.insert(make_pair(CcId,Temp.push_back(TagId)));

尝试:

if ( CCTagMap.find( CcId ) == CCTagMap.end() )
{
    CCTagMap.insert(make_pair(CcId,vector<int>()));
}
CCTagMap[CcId].push_back( TagId );

甚至更好,

map <int, vector<int> >::iterator iter = CCTagMap.find(CcId);
if ( iter == CCTagMap.end() )
{
    CCTagMap.insert(make_pair(CcId,vector<int>())).first->second.push_back( TagId );
}
else
{
    iter->second.push_back( TagId );
}

答案 3 :(得分:1)

这个怎么样?而不是CCTagMap,定义:

std::vector<std::vector<int> > clusters;

然后为每个TagIdCcId执行:

if (clusters.size() <= CcId)
  clusters.resize(CcId + 1);
clusters[CcId].append(TagId);