{"id":13615095,"url":"https://github.com/dominikbraun/graph","last_synced_at":"2025-05-14T11:11:25.217Z","repository":{"id":36994650,"uuid":"449811452","full_name":"dominikbraun/graph","owner":"dominikbraun","description":"A library for creating generic graph data structures and modifying, analyzing, and visualizing them.","archived":false,"fork":false,"pushed_at":"2024-06-15T08:04:47.000Z","size":429,"stargazers_count":1814,"open_issues_count":53,"forks_count":96,"subscribers_count":15,"default_branch":"main","last_synced_at":"2024-10-29T15:40:06.464Z","etag":null,"topics":["algorithm","graph","graph-algorithms","graph-library","graph-theory","graph-traversal","graph-visualization","graphs","graphviz","visualization"],"latest_commit_sha":null,"homepage":"https://graph.dominikbraun.io","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dominikbraun.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["dominikbraun"]}},"created_at":"2022-01-19T18:34:47.000Z","updated_at":"2024-10-25T15:27:41.000Z","dependencies_parsed_at":"2024-05-30T03:15:33.343Z","dependency_job_id":"9c1650f1-7189-471a-9700-03bb8e038d44","html_url":"https://github.com/dominikbraun/graph","commit_stats":null,"previous_names":[],"tags_count":36,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dominikbraun%2Fgraph","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dominikbraun%2Fgraph/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dominikbraun%2Fgraph/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dominikbraun%2Fgraph/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dominikbraun","download_url":"https://codeload.github.com/dominikbraun/graph/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247968368,"owners_count":21025823,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["algorithm","graph","graph-algorithms","graph-library","graph-theory","graph-traversal","graph-visualization","graphs","graphviz","visualization"],"created_at":"2024-08-01T20:01:09.310Z","updated_at":"2025-04-09T03:10:09.569Z","avatar_url":"https://github.com/dominikbraun.png","language":"Go","readme":"[中文版](README_CN.md) | [English Version](README.md)\n\n# \u003cimg src=\"img/banner.png\"\u003e\n\nA library for creating generic graph data structures and modifying, analyzing,\nand visualizing them.\n\n**Are you using graph? [Check out the graph user survey.](https://forms.gle/MLKUZKMeCRxTfj4v9)**\n\n# Features\n\n* Generic vertices of any type, such as `int` or `City`.\n* Graph traits with corresponding validations, such as cycle checks in acyclic graphs.\n* Algorithms for finding paths or components, such as shortest paths or strongly connected components.\n* Algorithms for transformations and representations, such as transitive reduction or topological order.\n* Algorithms for non-recursive graph traversal, such as DFS or BFS.\n* Vertices and edges with optional metadata, such as weights or custom attributes.\n* Visualization of graphs using the DOT language and Graphviz.\n* Integrate any storage backend by using your own `Store` implementation.\n* Extensive tests with ~90% coverage, and zero dependencies.\n\n\u003e Status: Because `graph` is in version 0, the public API shouldn't be considered stable.\n\n\u003e This README may contain unreleased changes. Check out the [latest documentation](https://pkg.go.dev/github.com/dominikbraun/graph).\n\n# Getting started\n\n```\ngo get github.com/dominikbraun/graph\n```\n\n# Quick examples\n\n## Create a graph of integers\n\n![graph of integers](img/simple.svg)\n\n```go\ng := graph.New(graph.IntHash)\n\n_ = g.AddVertex(1)\n_ = g.AddVertex(2)\n_ = g.AddVertex(3)\n_ = g.AddVertex(4)\n_ = g.AddVertex(5)\n\n_ = g.AddEdge(1, 2)\n_ = g.AddEdge(1, 4)\n_ = g.AddEdge(2, 3)\n_ = g.AddEdge(2, 4)\n_ = g.AddEdge(2, 5)\n_ = g.AddEdge(3, 5)\n```\n\n## Create a directed acyclic graph of integers\n\n![directed acyclic graph](img/dag.svg)\n\n```go\ng := graph.New(graph.IntHash, graph.Directed(), graph.Acyclic())\n\n_ = g.AddVertex(1)\n_ = g.AddVertex(2)\n_ = g.AddVertex(3)\n_ = g.AddVertex(4)\n\n_ = g.AddEdge(1, 2)\n_ = g.AddEdge(1, 3)\n_ = g.AddEdge(2, 3)\n_ = g.AddEdge(2, 4)\n_ = g.AddEdge(3, 4)\n```\n\n## Create a graph of a custom type\n\nTo understand this example in detail, see the [concept of hashes](https://pkg.go.dev/github.com/dominikbraun/graph#hdr-Hashes).\n\n```go\ntype City struct {\n    Name string\n}\n\ncityHash := func(c City) string {\n    return c.Name\n}\n\ng := graph.New(cityHash)\n\n_ = g.AddVertex(london)\n```\n\n## Create a weighted graph\n\n![weighted graph](img/cities.svg)\n\n```go\ng := graph.New(cityHash, graph.Weighted())\n\n_ = g.AddVertex(london)\n_ = g.AddVertex(munich)\n_ = g.AddVertex(paris)\n_ = g.AddVertex(madrid)\n\n_ = g.AddEdge(\"london\", \"munich\", graph.EdgeWeight(3))\n_ = g.AddEdge(\"london\", \"paris\", graph.EdgeWeight(2))\n_ = g.AddEdge(\"london\", \"madrid\", graph.EdgeWeight(5))\n_ = g.AddEdge(\"munich\", \"madrid\", graph.EdgeWeight(6))\n_ = g.AddEdge(\"munich\", \"paris\", graph.EdgeWeight(2))\n_ = g.AddEdge(\"paris\", \"madrid\", graph.EdgeWeight(4))\n```\n\n## Perform a Depth-First Search\n\nThis example traverses and prints all vertices in the graph in DFS order.\n\n![depth-first search](img/dfs.svg)\n\n```go\ng := graph.New(graph.IntHash, graph.Directed())\n\n_ = g.AddVertex(1)\n_ = g.AddVertex(2)\n_ = g.AddVertex(3)\n_ = g.AddVertex(4)\n\n_ = g.AddEdge(1, 2)\n_ = g.AddEdge(1, 3)\n_ = g.AddEdge(3, 4)\n\n_ = graph.DFS(g, 1, func(value int) bool {\n    fmt.Println(value)\n    return false\n})\n```\n\n```\n1 3 4 2\n```\n\n## Find strongly connected components\n\n![strongly connected components](img/scc.svg)\n\n```go\ng := graph.New(graph.IntHash)\n\n// Add vertices and edges ...\n\nscc, _ := graph.StronglyConnectedComponents(g)\n\nfmt.Println(scc)\n```\n\n```\n[[1 2 5] [3 4 8] [6 7]]\n```\n\n## Find the shortest path\n\n![shortest path algorithm](img/dijkstra.svg)\n\n```go\ng := graph.New(graph.StringHash, graph.Weighted())\n\n// Add vertices and weighted edges ...\n\npath, _ := graph.ShortestPath(g, \"A\", \"B\")\n\nfmt.Println(path)\n```\n\n```\n[A C E B]\n```\n\n## Find spanning trees\n\n![minimum spanning tree](img/mst.svg)\n\n```go\ng := graph.New(graph.StringHash, graph.Weighted())\n\n// Add vertices and edges ...\n\nmst, _ := graph.MinimumSpanningTree(g)\n```\n\n## Perform a topological sort\n\n![topological sort](img/topological-sort.svg)\n\n```go\ng := graph.New(graph.IntHash, graph.Directed(), graph.PreventCycles())\n\n// Add vertices and edges ...\n\n// For a deterministic topological ordering, use StableTopologicalSort.\norder, _ := graph.TopologicalSort(g)\n\nfmt.Println(order)\n```\n\n```\n[1 2 3 4 5]\n```\n\n## Perform a transitive reduction\n\n![transitive reduction](img/transitive-reduction-before.svg)\n\n```go\ng := graph.New(graph.StringHash, graph.Directed(), graph.PreventCycles())\n\n// Add vertices and edges ...\n\ntransitiveReduction, _ := graph.TransitiveReduction(g)\n```\n\n![transitive reduction](img/transitive-reduction-after.svg)\n\n## Prevent the creation of cycles\n\n![cycle checks](img/cycles.svg)\n\n```go\ng := graph.New(graph.IntHash, graph.PreventCycles())\n\n_ = g.AddVertex(1)\n_ = g.AddVertex(2)\n_ = g.AddVertex(3)\n\n_ = g.AddEdge(1, 2)\n_ = g.AddEdge(1, 3)\n\nif err := g.AddEdge(2, 3); err != nil {\n    panic(err)\n}\n```\n\n```\npanic: an edge between 2 and 3 would introduce a cycle\n```\n\n## Visualize a graph using Graphviz\n\nThe following example will generate a DOT description for `g` and write it into the given file.\n\n```go\ng := graph.New(graph.IntHash, graph.Directed())\n\n_ = g.AddVertex(1)\n_ = g.AddVertex(2)\n_ = g.AddVertex(3)\n\n_ = g.AddEdge(1, 2)\n_ = g.AddEdge(1, 3)\n\nfile, _ := os.Create(\"./mygraph.gv\")\n_ = draw.DOT(g, file)\n```\n\nTo generate an SVG from the created file using Graphviz, use a command such as the following:\n\n```\ndot -Tsvg -O mygraph.gv\n```\n\nThe `DOT` function also supports rendering graph attributes:\n\n```go\n_ = draw.DOT(g, file, draw.GraphAttribute(\"label\", \"my-graph\"))\n```\n\n### Draw a graph as in this documentation\n\n![simple graph](img/simple.svg)\n\nThis graph has been rendered using the following program:\n\n```go\npackage main\n\nimport (\n\t\"os\"\n\n\t\"github.com/dominikbraun/graph\"\n\t\"github.com/dominikbraun/graph/draw\"\n)\n\nfunc main() {\n\tg := graph.New(graph.IntHash)\n\n\t_ = g.AddVertex(1, graph.VertexAttribute(\"colorscheme\", \"blues3\"), graph.VertexAttribute(\"style\", \"filled\"), graph.VertexAttribute(\"color\", \"2\"), graph.VertexAttribute(\"fillcolor\", \"1\"))\n\t_ = g.AddVertex(2, graph.VertexAttribute(\"colorscheme\", \"greens3\"), graph.VertexAttribute(\"style\", \"filled\"), graph.VertexAttribute(\"color\", \"2\"), graph.VertexAttribute(\"fillcolor\", \"1\"))\n\t_ = g.AddVertex(3, graph.VertexAttribute(\"colorscheme\", \"purples3\"), graph.VertexAttribute(\"style\", \"filled\"), graph.VertexAttribute(\"color\", \"2\"), graph.VertexAttribute(\"fillcolor\", \"1\"))\n\t_ = g.AddVertex(4, graph.VertexAttribute(\"colorscheme\", \"ylorbr3\"), graph.VertexAttribute(\"style\", \"filled\"), graph.VertexAttribute(\"color\", \"2\"), graph.VertexAttribute(\"fillcolor\", \"1\"))\n\t_ = g.AddVertex(5, graph.VertexAttribute(\"colorscheme\", \"reds3\"), graph.VertexAttribute(\"style\", \"filled\"), graph.VertexAttribute(\"color\", \"2\"), graph.VertexAttribute(\"fillcolor\", \"1\"))\n\n\t_ = g.AddEdge(1, 2)\n\t_ = g.AddEdge(1, 4)\n\t_ = g.AddEdge(2, 3)\n\t_ = g.AddEdge(2, 4)\n\t_ = g.AddEdge(2, 5)\n\t_ = g.AddEdge(3, 5)\n\n\tfile, _ := os.Create(\"./simple.gv\")\n\t_ = draw.DOT(g, file)\n}\n```\n\nIt has been rendered using the `neato` engine:\n\n```\ndot -Tsvg -Kneato -O simple.gv\n```\n\nThe example uses the [Brewer color scheme](https://graphviz.org/doc/info/colors.html#brewer) supported by Graphviz.\n\n## Storing edge attributes\n\nEdges may have one or more attributes which can be used to store metadata. Attributes will be taken\ninto account when [visualizing a graph](#visualize-a-graph-using-graphviz). For example, this edge\nwill be rendered in red color:\n\n```go\n_ = g.AddEdge(1, 2, graph.EdgeAttribute(\"color\", \"red\"))\n```\n\nTo get an overview of all supported attributes, take a look at the\n[DOT documentation](https://graphviz.org/doc/info/attrs.html).\n\nThe stored attributes can be retrieved by getting the edge and accessing the `Properties.Attributes`\nfield.\n\n```go\nedge, _ := g.Edge(1, 2)\ncolor := edge.Properties.Attributes[\"color\"] \n```\n\n## Storing edge data\n\nIt is also possible to store arbitrary data inside edges, not just key-value string pairs. This data\nis of type `any`.\n\n```go\n_  = g.AddEdge(1, 2, graph.EdgeData(myData))\n```\n\nThe stored data can be retrieved by getting the edge and accessing the `Properties.Data` field.\n\n```go\nedge, _ := g.Edge(1, 2)\nmyData := edge.Properties.Data \n```\n\n### Updating edge data\n\nEdge properties can be updated using `Graph.UpdateEdge`. The following example adds a new `color`\nattribute to the edge (A,B) and sets the edge weight to 10.\n\n```go\n_ = g.UpdateEdge(\"A\", \"B\", graph.EdgeAttribute(\"color\", \"red\"), graph.EdgeWeight(10))\n```\n\nThe method signature and the accepted functional options are exactly the same as for `Graph.AddEdge`.\n\n## Storing vertex attributes\n\nVertices may have one or more attributes which can be used to store metadata. Attributes will be\ntaken into account when [visualizing a graph](#visualize-a-graph-using-graphviz). For example, this\nvertex will be rendered in red color:\n\n```go\n_ = g.AddVertex(1, graph.VertexAttribute(\"style\", \"filled\"))\n```\n\nThe stored data can be retrieved by getting the vertex using `VertexWithProperties` and accessing\nthe `Attributes` field.\n\n```go\nvertex, properties, _ := g.VertexWithProperties(1)\nstyle := properties.Attributes[\"style\"]\n```\n\nTo get an overview of all supported attributes, take a look at the\n[DOT documentation](https://graphviz.org/doc/info/attrs.html).\n\n## Store the graph in a custom storage\n\nYou can integrate any storage backend by implementing the `Store` interface and initializing a new\ngraph with it:\n\n```go\ng := graph.NewWithStore(graph.IntHash, myStore)\n```\n\nTo implement the `Store` interface appropriately, take a look at the [documentation](https://pkg.go.dev/github.com/dominikbraun/graph#Store).\n[`graph-sql`](https://github.com/dominikbraun/graph-sql) is a ready-to-use SQL store implementation.\n\n# Documentation\n\nThe full documentation is available at [pkg.go.dev](https://pkg.go.dev/github.com/dominikbraun/graph).\n\n**Are you using graph? [Check out the graph user survey.](https://forms.gle/MLKUZKMeCRxTfj4v9)**\n","funding_links":["https://github.com/sponsors/dominikbraun"],"categories":["Go","语言资源库","\u003ca name=\"Go\"\u003e\u003c/a\u003eGo"],"sub_categories":["go"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdominikbraun%2Fgraph","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdominikbraun%2Fgraph","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdominikbraun%2Fgraph/lists"}