簡體   English   中英

Boost Graph Library:添加具有相同標識的頂點

[英]Boost Graph Library: Adding vertices with same identification

如何使用 BGL 表示文件路徑? 考慮如下路徑: root/a/a/a/a/a

對應的圖是 'root'->'a'->'a'->...

是否可以添加多個共享相同名稱的頂點? 找不到明確的答案。

當然。 只要名稱不是標識符(身份意味着唯一)。

文件系統路徑的整體思想是路徑唯一的。 因此,您可能想要的是將唯一名稱作為節點的路徑,並在顯示時選擇要顯示的路徑部分。

對於使用內部頂點名稱的優雅演示¹:

using G = boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, fs::path>;
using V = G::vertex_descriptor;

現在您可以向圖形添加任何路徑:

void add_path(fs::path p, G& g) {
    if (p.empty()) return;
    if (!p.has_root_path()) p = fs::absolute(p);

    std::optional<V> prev;
    fs::path curr;
    for (auto const& el : p) {
        curr /= el;
        auto v = add_vertex(curr, g);
        if (prev)
            add_edge(*prev, v, g);
        prev = v;
    }
}

我們必須告訴 BGL 使用std::identityfs::path獲取內部名稱:

template <> struct boost::graph::internal_vertex_name<fs::path> {
    struct type : std::identity {
        using result_type = fs::path;
    };
};

現在,演示:

G g;

add_path("/root/a/a/a/a/a", g);
add_path("test.cpp", g);

要使用頂點 ID 進行打印:

print_graph(g);

要使用唯一節點路徑進行打印:

auto paths = get(boost::vertex_bundle, g);
print_graph(g, paths);

僅使用本地名稱打印:

auto filename = std::mem_fn(&fs::path::filename);
auto local    = make_transform_value_property_map(filename, paths);
print_graph(g, local);

現場演示

在編譯器資源管理器上運行

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graph_utility.hpp>
#include <boost/property_map/transform_value_property_map.hpp>
#include <filesystem>
using std::filesystem::path;

template <>
struct boost::graph::internal_vertex_name<path> {
    struct type : std::identity {
        using result_type = path;
    };
};

using G =
    boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, path>;
using V = G::vertex_descriptor;

void add_path(path p, G& g) {
    if (p.empty()) return;
    if (!p.has_root_path()) p = absolute(p);

    std::optional<V> prev;
    path curr;
    for (auto const& el : p) {
        curr /= el;
        auto v = add_vertex(curr, g);
        if (prev) add_edge(*prev, v, g);
        prev = v;
    }
}

int main() {
    G g;

    add_path("/root/a/a/a/a/a", g);
    add_path("test.cpp", g);

    // To print using the vertex ids:
    print_graph(g, std::cout << " ---- vertex index\n");

    // To print using the unique node paths:
    auto paths = get(boost::vertex_bundle, g);
    print_graph(g, paths, std::cout << " --- node path\n");

    // To print using only the local names:
    auto filename = std::mem_fn(&path::filename);
    auto local = make_transform_value_property_map(filename, paths);
    print_graph(g, local, std::cout << " --- local name\n");
}

打印(在我的機器上, test.cpp存在於/home/sehe/Projects/stackoverflow中):

 ---- vertex index
0 --> 1 7
1 --> 2
2 --> 3
3 --> 4
4 --> 5
5 --> 6
6 -->
7 --> 8
8 --> 9
9 --> 10
10 --> 11
11 -->
 --- node path
"/" --> "/root" "/home"
"/root" --> "/root/a"
"/root/a" --> "/root/a/a"
"/root/a/a" --> "/root/a/a/a"
"/root/a/a/a" --> "/root/a/a/a/a"
"/root/a/a/a/a" --> "/root/a/a/a/a/a"
"/root/a/a/a/a/a" -->
"/home" --> "/home/sehe"
"/home/sehe" --> "/home/sehe/Projects"
"/home/sehe/Projects" --> "/home/sehe/Projects/stackoverflow"
"/home/sehe/Projects/stackoverflow" --> "/home/sehe/Projects/stackoverflow/test.cpp"
"/home/sehe/Projects/stackoverflow/test.cpp" -->
 --- local name
"" --> "root" "home"
"root" --> "a"
"a" --> "a"
"a" --> "a"
"a" --> "a"
"a" --> "a"
"a" -->
"home" --> "sehe"
"sehe" --> "Projects"
"Projects" --> "stackoverflow"
"stackoverflow" --> "test.cpp"
"test.cpp" -->

獎金

圖表可視化 output:

write_graphviz(std::cout, g, boost::label_writer{local});

這個graphviz

在此處輸入圖像描述

¹ 參見例如如何配置 boost::graph 以使用我自己的(穩定的)索引作為頂點?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM