C ++设置如何按值对集合进行排序并按键搜索

时间:2016-07-24 23:47:45

标签: c++ set a-star

我正在实施A*最短路径算法。 Openlist部分存储将要访问的所有节点。该列表就像一个优先级队列,第一个元素具有最小的成本值,因此在每次迭代中,我们只需弹出第一个元素并访问它。但是在迭代中,我们需要遍历此节点的邻居并检查邻居是否在Openlist中。

这意味着这个Openlist需要支持两种类型的操作:

  1. 自动排序
  2. 查找节点(按其ID)
  3. 这里的问题是Openlist将按成本值排序,而查找需要基于邻居节点(相邻节点)的ID。所以我在考虑使用set,其中元素是节点。但是我不知道如何通过它在这个集合中的ID来查找元素。

    struct astar_node
    {
        string id;
        double f;  //estimated cost;
        double g;  //distance from source to this node;
        double h;  //heuristic cost from this node to target;
    };  
    
    struct openlist_compare
    {
        bool operator()(const astar_node &node1, const astar_node &node2 ){
               return node1.f < node2.f ;
        }
    };
    
    std::set<astar_node, openlist_compare> Openlist;
    

1 个答案:

答案 0 :(得分:1)

C ++容器,如std::setstd::mapstd::liststd::vector以及其他容器,是&#34;单一目的&#34;或&#34原语&#34;容器。每一个都具有某些独特的特性,使它们与其他容器区别开来;否则,当然没有理由首先拥有所有这些容器。

std::set的目的是按值查找容器中的值,并在集合中仅存储唯一值,即

与其他关联容器一样,std::set允许您指定一个可选的比较器类,它实际上指定了&#34;值&#34;表示对于容器中的每个实际值。而且,您已经这样做了,实际上,只定义了f类的astar_node成员,这对于定义集合包含的内容很重要。 astar_node的所有其他成员的所有其他值都将被忽略。

一旦完成,就std::set而言,就是这样。该集可以由astar_node::f查找,就是这样。这是在集合中查找内容的唯一方法。

正如我在开始时所说的那样,std::set和其他人是&#34;原始&#34;容器,有时你会需要一些更复杂的东西,就像这里的情况一样。在这种情况下,您可以使用多个容器,并以实现所需结果的方式组合它们。没有法律禁止使用多个容器来存储单组数据。没有法律规定您必须使用单个容器来执行您需要执行的所有操作,并使用特定的数据集合。

在此,据我所知,您还需要能够通过astar_node值在集合中找到id

精细:

typedef std::set<astar_node, openlist_compare> openlist_t;

openlist_t Openlist;

std::map<std::string, openlist_t::iterator> OpenList_by_id;

insert() astar_node OpenList insert()之后,openlist_t会返回astar_node中新元素的迭代器。您将获得插入的OpenList_by_id的迭代器。取这个迭代器,并将其放入id,密钥为OpenList

现在,如果要在id中找到remove的内容,请使用地图查找迭代器,然后取消引用它。问题解决了。

此外:

  1. astar_node()来自std::set的{​​{1}}也需要从OpenList_by_id查找地图中删除其迭代器。

  2. 由于std::set包含唯一值,因此您需要处理集合中已存在astar_node f的情况,并适当处理此情况。