【问题标题】:optimising the re-arranging of a map into a vector of vector优化将地图重新​​排列为向量的向量
【发布时间】:2011-11-30 12:17:05
【问题描述】:

我有一个包含整数值的地图。我想把这张地图重新排列成一个向量,这样所有的公共元素都在一个向量内。所以,我已经实现了以下代码。 但问题是我的地图在两个方向都包含大量数据。所以,我担心我的方法很慢,因为我总是在擦除地图的元素。所以,我想改进这个方法。你认为擦除元素是最好的方法。如果您知道,请给我一些其他有效的方法。如果您认为我的方法仍然可以改进,请修改我的代码。我已经提供了一个示例数据,我的数据看起来如何让您了解。 我希望这个向量向量为每个常见元素放置一个唯一标签。 提前谢谢你。

//populate my map from the upper part of my program

vector<int> list;
vector<vector<int> > listoflist;
map<int,vector<int> >::iterator it;
vector<int>::const_iterator any, is_in;

while (!my_map.empty()){
         it = my_map.begin();
         list.push_back(it->first);
         list.insert(list.end(), (it->second).begin(), (it->second).end());
         my_map.erase(it); // erase by iterator
         //go to next key and take its elements, if one is not inside add into list
         int newsize = list.size();
         for (int next=1; next<newsize; next++){          
              vector<int>& neb_to_next_element = my_map[list[next]];                
              for (any=neb_to_next_element.begin();
                     any!=neb_to_next_element.end(); any++){            
                   is_in = find (list.begin(), list.end(), *any);           
                   if(is_in==list.end()) list.push_back(*any);
              }
              //remove next now
              my_map.erase(list[next]);
              newsize = list.size();      
         }
         listoflist.push_back(list);
         list.clear();
}

这是我的地图的一部分

5 7 9
7 5 9 11
9 5 7 11
11 7 9
14 15 16 17
15 14 17
16 14 17 21
17 14 15 16 21
21 16 17
25 26
26 25

我想要一个向量的向量,如下所示

5 7 9 11
14 15 16 17 21
25 26

期待您的建议。

【问题讨论】:

  • 提问时,你应该很清楚原来的问题是什么。特别是第一段中connected的定义是什么?地图包含什么(除了整数,它们代表什么,键是什么)?你想要向量的输出向量是什么?
  • @David Rodríguez - dribeas:我已经修改了帖子。我希望向量的向量将所有常见的元素分别用于其他部分。可能是,我可以使用多映射,但我不知道在这种情况下如何添加另一个等于我的 vec 的索引的键。
  • 问题还不是很清楚(代码太多,但解释不够),但我的理解是你想构建在地图的任何条目中一起出现的元素集,即也就是说,如果a -&gt; b, cb -&gt; d 两个集合都应该合并到a, b, c, d 中,是这样吗?
  • @DavidRodríguez-dribeas:我回滚了您的编辑,我希望没关系,因为尽管 g_niro 邀请他修改他的代码,但我认为对其中的代码进行实质性更改并不是一个好主意问题本身。 (毕竟,它不再是同一个问题!)
  • @ruakh:代码完全一样,我只是重新排列变量的定义以更接近用法,从而避免来回走动。代码没有实质性更改,因为编译器会为两个版本生成相同的代码

标签: c++ map iterator


【解决方案1】:

如何为输出创建一个集合向量:

typedef std::set<int>                   one_collection;
typedef std::vector<one_collection>     all_collections;
typedef std::map<int, std::vector<int>> source_data;

source_data     src;
all_collections dst;

while (!src.empty())
{
    dst.push_back(one_collection());
    one_collection & c = dst.back();

    source_data::const_iterator const it = src.begin();

    c.insert(it->first);
    c.insert(it->second.begin(), it->second.end());

    src.erase(it);

    for (one_collection::const_iterator jt = c.begin(), end = c.end(); jt != end; ++jt)
    {
        source_data::const_iterator const kt = src.find(*jt);

        if (kt == src.end()) continue;

        c.insert(kt->second.begin(), kt->second.end());
        src.erase(kt);
    }
}

现在dst 中的每个集合都应该包含一个“连接集合”。

(在 C++11 之前,您的迭代器可能必须是可变迭代器,因为 erase() 之前已损坏。)

【讨论】:

  • 谢谢,我正在使用 dev c++。我希望,我可以用 Dev 实现这段代码。
  • 不是集合的向量,这个搜索条件比我的搜索方法快吗?请让我知道。因为我喜欢这样
  • @g_niro:是的,它更快,因为set 按值查找比vector 更快。不过,如果需要,您始终可以将结果集复制回向量中。
  • 感谢您的代码。另外,我想了解您的元素搜索策略(查找并继续),因为它与我的有点不同。我想你的方式也更快。是吗?
【解决方案2】:

我担心我的方法很慢,因为我总是在擦除地图中的元素。

您不必担心此特定操作。从地图中擦除元素并不是一项非常昂贵的操作(O( log N ),与从向量中擦除 O(N) 相比)。

另一方面,还有其他可以改进的操作,例如,构建中间集而不是在list 向量中查找元素是否仍然存在。集合中的查找是O(log N),而向量中的查找是O(N)。这是理论上的复杂性,好像元素的数量相当少,隐藏的常数可能会改变平衡(在一个集合中,每个插入的元素都有一个动态分配,而在一个向量中只会有几个重新分配,这意味着如果 N 很小,向量查找的线性时间可能会被较少的动态分配量补偿)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-01
    相关资源
    最近更新 更多