Documentation ¶
Overview ¶
This package provides a basic graph structure, along with some of the popular algorithms in graph theory.
Index ¶
- type Graph
- func (g *Graph) AddLink(startNode fmt.Stringer, endNode fmt.Stringer, weight int) bool
- func (g *Graph) AddNode(node fmt.Stringer) bool
- func (g *Graph) BFS(start fmt.Stringer) [][]fmt.Stringer
- func (g *Graph) ConnectedComponents() [][]fmt.Stringer
- func (g *Graph) DFS(start fmt.Stringer) []Link
- func (g Graph) EulerPath() []Link
- func (g *Graph) Export(highlights []Link, ordered bool, clusters [][]fmt.Stringer) string
- func (g *Graph) Floyd() map[fmt.Stringer]map[fmt.Stringer]int
- func (g *Graph) HamiltonPath() []Link
- func (g *Graph) HasCycle() bool
- func (g *Graph) IncomingLinksCount(node fmt.Stringer) int
- func (g *Graph) IsBipartite() bool
- func (g *Graph) IsPlanar() bool
- func (g *Graph) Links() []Link
- func (g *Graph) MST() []Link
- func (g *Graph) MaxFlow(source fmt.Stringer, sink fmt.Stringer) int
- func (g *Graph) MinPaths(start fmt.Stringer) map[fmt.Stringer]int
- func (g *Graph) Nodes() []fmt.Stringer
- func (g *Graph) OutgoingLinksCount(node fmt.Stringer) int
- func (g *Graph) ReachableNodes(node fmt.Stringer) []fmt.Stringer
- func (g *Graph) RemoveLink(startNode fmt.Stringer, endNode fmt.Stringer) bool
- func (g *Graph) RemoveNode(node fmt.Stringer) bool
- func (g *Graph) String() string
- type Interface
- type Link
- type Node
- type Queue
Examples ¶
- Graph.AddLink
- Graph.AddNode
- Graph.BFS
- Graph.ConnectedComponents
- Graph.DFS
- Graph.EulerPath
- Graph.Export
- Graph.Floyd
- Graph.HamiltonPath
- Graph.HasCycle
- Graph.IncomingLinksCount
- Graph.IsBipartite
- Graph.IsPlanar
- Graph.Links
- Graph.MST
- Graph.MaxFlow
- Graph.MinPaths (Dijkstra)
- Graph.MinPaths (FordBellman)
- Graph.Nodes
- Graph.OutgoingLinksCount
- Graph.ReachableNodes
- Graph.RemoveLink
- Graph.RemoveNode
- Graph.String
- Link.String
- Node.AdjacentNodes
- ReadGraph
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Graph ¶
type Graph struct { // Whether the graph is oriented or not takes effect on the // visual representation as well as edge addition to it. Oriented bool // If the graph is weighed, the weights will be shown on the // exported visualization, otherwise an edge between two nodes // will be represented by a weight of 1 Weighed bool // Whether or not the graph has negative weights takes effect // on which algorithms to use in some cases like shorted path // finding. HasNegativeWeights bool // contains filtered or unexported fields }
func ReadGraph ¶
Creates a graph, read from a string with an expected input format such as: <oriented> <weighed> <hasNegativeWeights> - booleans <node> - for adding a node <node> -- <node> [<weight>] - for adding a link If 'reversed' is true, the graph will be constructed with reversed edges.
Example ¶
data, _ := ioutil.ReadFile("exampleGraph.txt") graph := ReadGraph(string(data), false) fmt.Println(graph)
Output: true true false alpha 2 3 2 -- 3 2
func (*Graph) AddLink ¶
Tries to add a link between two nodes and returns true if successful, otherwise returns false if such a link already exists.
Note: If the graph isn't oriented adding a link from A to B effectively adds a link from B to A.
Example ¶
graph := NewGraph(false, true, false) fmt.Println(graph.AddLink(stringer("a"), stringer("b"), 2)) fmt.Println(graph.AddLink(stringer("a"), stringer("b"), 5))
Output: true false
func (*Graph) AddNode ¶
Tries to add a node to the graph and returns true if successful, otherwise returns false if the node already exists.
Example ¶
graph := NewGraph(false, true, false) fmt.Println(graph.AddNode(stringer("a"))) fmt.Println(graph.AddNode(stringer("a"))) fmt.Println(graph.AddNode(stringer("b")))
Output: true false true
func (*Graph) BFS ¶
Traverses the graph in a manner of breadth first search and returns a slice of slices of node names, representing the layers of nodes during the search, with the first layer with index 0 containing the initial node.
Example ¶
fmt.Println(createGrapht().BFS(stringer("2")))
Output: [[2] [3 4] [5]]
func (*Graph) ConnectedComponents ¶
Return a slice of slices where are given the nodes in each separate strongly connected component.
Example ¶
fmt.Println(createGraphc().ConnectedComponents()) fmt.Println(createGraphc2().ConnectedComponents())
Output: [[3 4 5 2] [alpha]] [[2] [3] [5] [4] [alpha]]
func (*Graph) DFS ¶
Traverses the graph in a manner of depth first search and returns a slice of links through which it goes during the search.
Example ¶
fmt.Println(createGrapht().DFS(stringer("2")))
Output: [2-(2)->3 3-(8)->5 5-(10)->4]
func (Graph) EulerPath ¶
Returns a slice of links representing an Eulearian path. If no such path exists, returns an empty slice. This algorithm works for undirected graphs for now.
Note: An Eulerian path is such that it traverses through every edge exactly once.
Example ¶
fmt.Println(createGraphsp().EulerPath()) fmt.Println(createGraphsp2().EulerPath())
Output: [3-(8)->5 5-(10)->4 4-(5)->2 2-(2)->3] []
func (*Graph) Export ¶
Export the graph structure in a format specified by the dot language used in graphviz, which can be loaded by the software and visualized. 'highlights' is a slice of links representing edges of the graph you would like to outline, for example the results of a DFS search and they will be colored red. 'ordered' is a boolean indicating whether or not the index of the links would be shown next to their name which is useful for distinguishing DFS from MST for example. 'clusters' is a 2d array of fmt.Stringers representing nodes that should be ordered in separate groups visually, if it's empty, the graph will be displayed as is.
Example ¶
graph := createGraphex() fmt.Println(graph.Export([]Link{}, false, [][]fmt.Stringer{})) fmt.Println(graph.Export(graph.DFS(stringer("2")), true, [][]fmt.Stringer{}))
Output: graph {"alpha" "2" "3" "4" "5" "2"--"3" [label="2"]; "2"--"4" [label="5"]; "3"--"5" [label="8"]; "4"--"5" [label="10"]; } graph {"2"--"3" [fontcolor=red color=red label="2 (1)"]; "3"--"5" [fontcolor=red color=red label="8 (2)"]; "5"--"4" [fontcolor=red color=red label="10 (3)"]; "alpha" "2"--"4" [label="5"]; }
func (*Graph) Floyd ¶
Returns a matrix of node names, where you can find the minimum distance between two nodes, given their names.
Example ¶
paths := createGraphd().Floyd() fmt.Println(paths[stringer("2")][stringer("5")]) fmt.Println(paths[stringer("3")][stringer("4")])
Output: 10 7
func (*Graph) HamiltonPath ¶
Returns a slice of links representing an Hamiltonian path. If no such path exists, returns an empty slice.
Note: A Hamiltonian path is such that it traverses through every vertex exactly once.
Example ¶
graph := createGraphsp() fmt.Println(graph.HamiltonPath()) graph.RemoveNode(stringer("alpha")) fmt.Println(graph.HamiltonPath())
Output: [] [2-(2)->3 3-(8)->5 5-(10)->4]
func (*Graph) HasCycle ¶
Returns a boolean value of whether or not the graph contains atleast one cycle, which means that some edges form a closed circle.
Example ¶
fmt.Println(createGraphpr().HasCycle()) fmt.Println(createGraphpr2().HasCycle()) fmt.Println(createGraphpr3().HasCycle())
Output: true true false
func (*Graph) IncomingLinksCount ¶
Returns the count of the links which have as an ending node the one specified as a parameter.
Note: If the graph isn't oriented the outgoing links will always match the incoming links.
Example ¶
graph := createGraph() fmt.Println(graph.IncomingLinksCount(stringer("alpha"))) fmt.Println(graph.IncomingLinksCount(stringer("2"))) fmt.Println(graph.IncomingLinksCount(stringer("3")))
Output: 1 3 2
func (*Graph) IsBipartite ¶
Returns a boolean value of whether or not the graph is bipartite, which means that it's vertices can be split into two groups where there aren't any edges between vertices of the same group.
Example ¶
graph := createGraphpr() fmt.Println(createGraphpr2().IsBipartite()) fmt.Println(graph.IsBipartite()) graph.AddLink(stringer("2"), stringer("5"), 20) fmt.Println(graph.IsBipartite())
Output: true true false
func (*Graph) IsPlanar ¶
Returns a boolean value of whether or not the graph is planar, which means that it can be drawn on a piece of paper with no two edges crossing.
Example ¶
graph := createGraphpr() graph.RemoveNode(stringer("alpha")) fmt.Println(graph.IsPlanar()) graph.AddLink(stringer("2"), stringer("5"), 20) graph.AddLink(stringer("3"), stringer("4"), 15) graph.AddLink(stringer("2"), stringer("alpha"), 1) graph.AddLink(stringer("3"), stringer("alpha"), 1) graph.AddLink(stringer("4"), stringer("alpha"), 1) graph.AddLink(stringer("5"), stringer("alpha"), 1) fmt.Println(graph.IsPlanar())
Output: true false
func (*Graph) Links ¶
Returns a slice with the all the links in the graph.
Example ¶
data, _ := ioutil.ReadFile("exampleGraph.txt") graph := ReadGraph(string(data), false) fmt.Println(graph.Links())
Output: [2-(2)->3]
func (*Graph) MST ¶
Returns a slice of the links constructing the minimal spanning tree for the given graph, according to Kruskal's algorithm.
Example ¶
fmt.Println(createGraphm().MST())
Output: [2-(2)->3 2-(5)->4 5-(8)->3]
func (*Graph) MaxFlow ¶
Returns the maximum ammount that can flow from the source to the sink for 1 period of time according to the min-cut max-flow algorithm.
Example ¶
graph := createGraphmf() fmt.Println(graph.MaxFlow(stringer("2"), stringer("5"))) fmt.Println(graph.MaxFlow(stringer("3"), stringer("4"))) fmt.Println(graph.MaxFlow(stringer("alpha"), stringer("4")))
Output: 7 10 0
func (*Graph) MinPaths ¶
Returns a map bound by node name, containing the minimum distance between the given node and all of the other nodes. Internally it chooses between Dijkstra's and Ford Bellman's algorithms depending on whether the graph has negative weights or not.
Example (Dijkstra) ¶
graph := createGraphd() fmt.Println(graph.MinPaths(stringer("2"))[stringer("5")]) fmt.Println(graph.MinPaths(stringer("3"))[stringer("4")])
Output: 10 7
Example (FordBellman) ¶
graph := createGraphNegative() fmt.Println(graph.MinPaths(stringer("2"))[stringer("5")]) fmt.Println(graph.MinPaths(stringer("3"))[stringer("4")])
Output: 5 -3
func (*Graph) Nodes ¶
Returns a slice with all the nodes in the graph.
Example ¶
fmt.Println(createGraph().Nodes())
Output: [alpha 2 3 4 5]
func (*Graph) OutgoingLinksCount ¶
Returns the count of the links which have as a starting node the one specified as a parameter.
Note: If the graph isn't oriented the outgoing links will always match the incoming links.
Example ¶
graph := createGraph() fmt.Println(graph.OutgoingLinksCount(stringer("alpha"))) fmt.Println(graph.OutgoingLinksCount(stringer("2"))) fmt.Println(graph.OutgoingLinksCount(stringer("3")))
Output: 1 3 2
func (*Graph) ReachableNodes ¶
Return a slice of all nodes to which a path exists from the node provided as a parameter.
Example ¶
graph := createGraphc() fmt.Println(graph.ReachableNodes(stringer("2"))) fmt.Println(graph.ReachableNodes(stringer("alpha")))
Output: [3 4 5] []
func (*Graph) RemoveLink ¶
Tries to remove the link from the graph and if successful returns true, otherwise if the link doesn't exist, returns false.
Note: If the graph isn't oriented removing the link from A to B effectively removes the link from B to A.
Example ¶
graph := NewGraph(false, true, false) graph.AddLink(stringer("a"), stringer("b"), 2) fmt.Println(graph.RemoveLink(stringer("a"), stringer("b"))) fmt.Println(graph.RemoveLink(stringer("a"), stringer("b"))) fmt.Println(graph.RemoveLink(stringer("a"), stringer("c")))
Output: true false false
func (*Graph) RemoveNode ¶
Tries to remove the node from the graph and if successful removes all links between it and other nodes and returns true, otherwise if the node doesn't exist, returns false.
Example ¶
graph := NewGraph(false, true, false) graph.AddNode(stringer("a")) fmt.Println(graph.RemoveNode(stringer("a"))) fmt.Println(graph.RemoveNode(stringer("a"))) fmt.Println(graph.RemoveNode(stringer("b")))
Output: true false false
func (*Graph) String ¶
A string representation of Graph, with an output format like the input format: <oriented> <weighed> <hasNegativeWeights> - booleans <node> - all nodes in the graph each on a separate line <node> -- <node> [<weight>] - for all the links
Example ¶
data, _ := ioutil.ReadFile("exampleGraph.txt") graph := ReadGraph(string(data), false) fmt.Println(graph)
Output: true true false alpha 2 3 2 -- 3 2
type Interface ¶
type Interface interface {
Less(other interface{}) bool
}
Only items implementing this interface can be enqueued on the priority queue.
type Node ¶
type Queue ¶
type Queue struct { Limit int // contains filtered or unexported fields }
Queue is a threadsafe priority queue exchange. Here's a trivial example of usage:
q := pqueue.New(0) go func() { for { task := q.Dequeue() println(task.(*CustomTask).Name) } }() for i := 0; i < 100; i := 1 { task := CustomTask{Name: "foo", priority: rand.Intn(10)} q.Enqueue(&task) }
func NewPriorityQueue ¶
New creates and initializes a new priority queue, taking a limit as a parameter. If 0 given, then queue will be unlimited.
func (*Queue) ChangeLimit ¶
Safely changes enqueued items limit. When limit is set to 0, then queue is unlimited.
func (*Queue) Dequeue ¶
Dequeue takes an item from the queue. If queue is empty then should block waiting for at least one item.