This is a creation in Article, where the information may have evolved or changed.
Undergraduate study data structure when listening to predecessors said, learn data structure, computer composition, operating system and computer network will become a great God, I also hard to learn, but has not found the use of data structures. The actual programming used more than the hash table, the general language will also be supported by some expansion packages.
The Nineth chapter of "The Beauty of Mathematics", "Graph theory and web crawler", introduces the actual use of the graph in simple and understandable ways. Search Engine crawler Crawl network data, that is, the Internet is abstracted into a graph of this data structure, by traversing the graph to achieve the Internet crawl.
Graphs are generally divided into graphs and graphs, generally used to develop web crawlers and maps (I know these two). A graph can be thought of as a collection of nodes and connected edges, in two ways: adjacency table and adjacency matrix. Sparse graphs are implemented by adjacency tables, and dense graphs are implemented by adjacency matrices. The focus of the graph is on traversal, with depth-first traversal and breadth-first traversal. The depth-first traversal can be implemented by recursion, while the breadth-first traversal is implemented to convert to a tree-like sequence traversal. Also note that the traversal of the graph to prevent the loop, otherwise it will not end the traversal.
type Graph struct {edgnum intvexnum intadj []Vertex}type Vertex struct {Data stringe *Edge}type Edge struct {ivex intnext *Edge}
Three structures are defined, which Graph is the data structure of the graph, which contains the set of edges, vertices and vertices Vertex , is the vertex data structure, contains the vertex's content and the edge of the head pointer, Edge The structure of the edge defines the position and the address of the next edge in the vertex collection of the graph with another vertex attached to the vertex.
A graph is a collection of vertices and edges, an adj object is a collection of vertices, and within each vertex e is a collection of edges that are implemented through a linked list. This also achieves the diagram.
Inserting vertices in the diagram is a simple one, adding a collection of vertices:
func (this *Graph) InsertVertex(v Vertex) {this.adj = append(this.adj, v)}
To insert an edge in the diagram, you need to indicate the information of the connected two vertices, and then insert the edge information into the end of the list:
func (this *Graph) InsertEdge(v1, v2 Vertex) {var p *Edge = this.adj[this.get_position(v1.Data)].eif p == nil {// fmt.Println("nil...", v1.Data, v2.Data)this.adj[this.get_position(v1.Data)].e = NewEdge(this.get_position(v2.Data))} else {for ; p.next != nil; p = p.next {}p.next = NewEdge(this.get_position(v2.Data))// fmt.Println("append...", v1.Data, v2.Data)}}
Gets the adjacency vertex of a vertex, finds the edge collection of the vertex, and finds the vertices connected to it through the edge collection. This method can also be used to calculate the degree of the vertex (out degree):
func (this *Graph) Adjacent(v Vertex) []Vertex {res := make([]Vertex, 0)p := this.adj[this.get_position(v.Data)].efor ; p != nil; p = p.next {res = append(res, this.adj[p.ivex])}return res}func (this *Graph) OutDegree(v Vertex) int {res := 0p := this.adj[this.get_position(v.Data)].efor p != nil {res++p = p.next}return res}
It is a bit cumbersome to calculate the penetration of vertices, because the set of edges that the diagram itself holds is the starting position of the edge, the end position, that is, the in degree, which can only be computed by traversing the entire set of edges:
func (this *Graph) InDegree(v Vertex) int {res := 0pos := this.get_position(v.Data)for _, a := range this.adj {p := a.efor p != nil {if pos == p.ivex {res++}p = p.next}}return res}
Breadth-first traversal, which is similar to a sequence traversal, where each layer is traversed, the nodes of the current layer need to be remembered, and then the nodes connected to the current layer are traversed, so the traversal is implemented. Requires a queue to remember the current layer, FIFO. I am a simple queue that is implemented through Golang slice . Another problem is the need to prevent loops, which means that a node cannot traverse two times. This uses the Golang built-in map implementation, random storage, random search. Traversal also to prevent the situation of incomplete graphs, if only the nodes have no edge also need to process, so here with the for loop to deal with:
func (this *Graph) Bfs() {res := map[int]Vertex{}for _, a := range this.adj {Q := []Vertex{a}for len(Q) != 0 {u := Q[0]Q = Q[1:]if _, ok := res[this.get_position(u.Data)]; !ok {Q = append(Q, this.Adjacent(u)...)res[this.get_position(u.Data)] = ufmt.Printf("%s ", u.Data)}}}fmt.Printf("\n")}
Depth-first traversal, traversing a node, and then traversing the node connected to the node, until the end. Recursion is very simple:
func (this *Graph) Dfs() {res := map[int]Vertex{}for _, a := range this.adj {this.dfs(a, res)}fmt.Printf("\n")}func (this *Graph) dfs(u Vertex, res map[int]Vertex) {if _, ok := res[this.get_position(u.Data)]; !ok {res[this.get_position(u.Data)] = ufmt.Printf("%s ", u.Data)p := u.efor p != nil {if _, ok := res[p.ivex]; !ok {this.dfs(this.adj[p.ivex], res)}p = p.next}}}
Complete test code, large Golang Unit test tool, can be directly go test :
func TestMain(t *testing.T) {g := create_example_lgraph()g.Print()println("Bfs.............")g.Bfs()println("Dfs.............")g.Dfs()if g.InDegree(Vertex{Data: "E"}) != 2 {t.Error("indegree of E wanted 2 bug got", g.InDegree(Vertex{Data: "E"}))}if g.OutDegree(Vertex{Data: "E"}) != 2 {t.Error("outdegree of E wanted 2 bug got", g.OutDegree(Vertex{Data: "E"}))}}func create_example_lgraph() *Graph {vexs := []string{"A", "B", "C", "D", "E", "F", "G"}edges := [][2]string{{"A", "B"},{"B", "C"},{"B", "E"},{"B", "F"},{"C", "E"},{"D", "C"},{"E", "B"},{"E", "D"},{"F", "G"}}vlen := len(vexs)elen := len(edges)pG := Create()// 初始化"顶点数"和"边数"pG.vexnum = vlenpG.edgnum = elen// 初始化"邻接表"的顶点for i := 0; i < pG.vexnum; i++ {pG.InsertVertex(*NewVertex(vexs[i]))}// 初始化"邻接表"的边for i := 0; i < pG.edgnum; i++ {// 读取边的起始顶点和结束顶点pG.InsertEdge(*NewVertex(edges[i][0]), *NewVertex(edges[i][1]))}return pG}
Please refer to the complete source code in this article.
###### References + "1" wangkuiwu/datastructs_and_algorithm-github+ "2" "Data structure and algorithm--c language description", Mark Allen Weiss + "3" algorithm introduction Thomas H. Cormen waiting + "4", "The Beauty of Mathematics" Wu
Original link: Golang through the adjacency table to achieve a map, reproduced please indicate the source!