使用multimap c ++打印邻接列表

时间:2014-10-09 09:27:12

标签: c++ graph map

我根据以下链接构建了一个邻接列表:Adjacency list


struct Node
{
    string name;
    int id;
};

typedef std::multimap<Node,Node> Graph;
Graph g;

g.insert (Graph::value_type(node1, node3));
g.insert (Graph::value_type(node1, node4));
g.insert (Graph::value_type(node1, node5));
g.insert (Graph::value_type(node2, node6));
g.insert (Graph::value_type(node3, node6));

如何按照下图(Adjacency list)的结构打印多图?

enter image description here

2 个答案:

答案 0 :(得分:3)

Graph::const_iterator it = g.begin();
while (it != g.end())
{
    std::pair<Graph::const_iterator, Graph::const_iterator> range
        = g.equal_range(it->first);

    std::cout << it->first << ": "; // print vertex

    for (; range.first != range.second; ++range.first)
    {
        std::cout << range.first->second << ", "; // print adjacent vertices
    }
    std::cout << std::endl;

    it = range.second;
}

输出:

1: 3, 4, 5, 
2: 6, 
3: 6, 
4: 7, 
5: 7, 8, 9, 
9: 5,

DEMO


如果您不想进行冗余 equal_range调用,只要两个相邻的元素相等,就可以使用单个迭代器进行操作订购条款:

Graph::key_compare cmp = g.key_comp();
Graph::const_iterator it = g.begin(), itEnd = g.end(), prev;
while (it != itEnd)
{
    std::cout << it->first << ": "; // print vertex

    do
    {
        std::cout << it->second << ", "; // print adjacent vertices
        prev = it++;
    }        
    while (it != itEnd && !cmp(prev->first, it->first));

    std::cout << std::endl;
}

DEMO 2

答案 1 :(得分:2)

以下替代解决方案使用C ++ 11的基于范围的for循环。它遍历所有条目,无论源节点如何,并将当前源节点与前一个节点进行比较。如果它们不同,请在输出中开始一个新行。

与使用equal_range的解决方案相比,此替代方案更加缓存友好:它只按节点的顺序迭代整个图形。 equal_range首先使用相同的源节点搜索范围的结尾,然后循环再次遍历这些元素。我的替代解决方案避免了这一点(当然,我没有做任何基准测试,这不是最终的最快解决方案,但我只想提供替代方案。)

std::ostream& operator<<(std::ostream& os, const Graph& g)
{
    auto prev = g.begin()->first;
    os << prev << ": ";
    for (auto e : g) {
        if (e.first < prev || prev < e.first)
            os << std::endl << (prev = e.first) << ": ";
        os << e.second << ", ";
    }
    return os << std::endl;
}

Live demo

如果您为operator!=类型实施Node,则if - 行可以简化为更具可读性的比较:

std::ostream& operator<<(std::ostream& os, const Graph& g)
{
    auto prev = g.begin()->first;
    os << prev << ": ";
    for (auto e : g) {
        if (e.first != prev) // <--- now more readable
            os << std::endl << (prev = e.first) << ": ";
        os << e.second << ", ";
    }
    return os << std::endl;
}