【问题标题】:Rgd: Vector Iterator to get Index PositionRgd:获取索引位置的向量迭代器
【发布时间】:2013-02-17 08:30:43
【问题描述】:

这是我的迭代器位置代码

struct node {
int nodeid;
vector<fingerTable> fTable;
vector<string> data;
};

vector<node> cNode;

vector<node>::iterator position = find(cNode.begin(),cNode.end(), id);

我有大约 100 个对象,我正在尝试查找例如 nodeid "80" 的索引/元素/位置,假设我的对象全部按 nodeid 升序排序。

我关心的是速度和内存使用,我以前使用过

for(int i=0;i<cNode.size();i++)
{
//if logic-- match nodeid with the nodeid input.. then assign the i to an integer..
}

但现在我正在尝试使用和迭代器,我听说它更快.. 任何关于修复它的建议,或者是否有更好的方法通过其值“nodeid”找到我的向量索引

我知道 map 对于我的情况来说是一个很好的标准容器,但我有点没时间做这些更改,所以我必须坚持使用向量。..

vector<node>::iterator position = find(cNode.begin(),cNode.end(), id);

当我尝试编译上面的迭代器行时输出错误。

In member function ‘void chord::removePeer(int)’:
testfile.cpp:532:69: error: no matching function for call to ‘chord::find(std::vector<chord::node>::iterator, std::vector<chord::node>::iterator, int&)’
testfile.cpp:532:69: note: candidate is:
testfile.cpp:177:5: note: int chord::find(int, int, bool)
testfile.cpp:177:5: note:   no known conversion for argument 1 from ‘std::vector<chord::node>::iterator {aka __gnu_cxx::__normal_iterator<chord::node*, std::vector<chord::node> >}’ to ‘int’

【问题讨论】:

标签: c++


【解决方案1】:

你有一个对象向量。每个对象都包含一个 int。您正试图在该向量中“找到”在该 int 中具有给定值的对象。但是编译器不理解这一点,因为 STL 只描述了如何在容器中查找值。不然怎么可能呢?如果你有一个包含两个 int 的对象,会比较哪一个?

既然你说使用 std::find() 是为了比老式的 for 循环有更好的性能,你现在可以停止尝试,回到过去。无论哪种方式,性能都将基本相同,并且您已经说过您没时间了。因此,只需使用您的工作,因为这不是性能问题。

如果您坚持使用迭代器,您可以使用 std::find_if() 和您定义的自定义谓词,如下所示:

struct HasId {
    HasId(int id) : _id(id) {}
    bool operator()(node const& n) const { return n.nodeid == _id; }
private:
    int _id;
}

std::find_if(cNode.begin(), cNode.end(), HasId(id));

这样,我们提供了足够的信息让 STL 找到我们感兴趣的元素,而无需创建临时节点来搜索。

【讨论】:

  • 你好,在 find if 的情况下,我如何获得返回结果作为我正在寻找的索引的向量[Index]。
  • find_if() 返回一个迭代器。如果它被称为iter,那么你可以说*iter 来取消引用它并得到与cNode[index] 相同的结果。如果你想知道你找到了哪个索引,请iter - cNode.begin()
  • 为什么需要索引?
  • @JohnZwinck 抱歉再次询问。我如何为此查找创建迭代器,然后执行 *iter,我是否创建整数类型的迭代器。谢谢。我尝试使用以下 vector::iterator iter; , 然后 iter = std::find_if(cNode.begin(), cNode.end(), HasId(id));
  • 请阅读我的回答的第二段:你最好回到你没有使用迭代器的代码。现在这些东西对你没有任何好处。
【解决方案2】:

cNode是node类型的向量但是你传入id(int type),你需要一个隐式转换函数将id转换为node对象:

struct node {
   int nodeid;
   vector<fingerTable> fTable;
   vector<string> data;

    node(int id)
    : nodeid(nodeid)
    {
    }
};

bool operator==(const node& lhs, const node& rhs)
{
  return lhs.nodeid == rhs.nodeid;
}

现在您可以在node 向量上调用整数类型的 std::find:

std::vector<node>::iterator position = std::find(cNode.begin(),cNode.end(), id);

等于:

std::vector<node>::iterator position = std::find(cNode.begin(),cNode.end(), node(id)); 

使用 C++11,您可以使用 std::find_if 作为替代方式编写 lambda:

auto pos = std::find_if(cNode.begin(), cNode.end(), 
           [id](const node& n){ return n.nodeid == id; } );

【讨论】:

    【解决方案3】:

    nNode 是向量,std::find 搜索值而不是键。使用类似的东西 std::map&lt;int,node&gt; 找到你的节点。

    int id = 0;
    
    typedef std::map<int,node> NodeMap;
    NodeMap cNode;
    
    NodeMap::iterator position = cNode.find(id);
    

    如果您要进行大量插入/删除操作并保持排序,请选择合适的容器,例如 map 或 set。

    这基本上又是C++ How to speed up my prog design

    如果您将节点更改为:

    struct node {
        vector<fingerTable> fTable;
        vector<string> data;
    };
    

    从矢量变为地图

    map<int,node> cNode;
    

    那么你的 addPeer 真的只这样做:

    void chord::addPeer(int id)
    {
        std::map<int, node>::iterator 
        pos = cNode.insert( std::make_pair(id, node() ) ).first;;
    
        if( pos != cNode.end() )
        {
            ++pos;
            vector<string> data = pos->second.data;
            pos->second.data.clear();
            dataShift( data, fIndex-1 );
        }
    }//end addPeer
    

    剩下的唯一问题是dataShift 做了什么,它需要索引吗?

    【讨论】:

      猜你喜欢
      • 2010-09-13
      • 2014-09-19
      • 2010-10-14
      • 1970-01-01
      • 1970-01-01
      • 2011-10-19
      • 2016-08-25
      • 1970-01-01
      • 2020-03-05
      相关资源
      最近更新 更多