Depth first search of graphs of commonly used data structures_breadth first search_spanning tree_prime algorithm_kruskal algorithm

1. Basic concepts of graphs

Earlier we talked about the relationship between data in three forms, one-to-one (linear table), one-to-many (tree), today we will talk about the third form of many-to-many data representation-graph. The first picture below, without arrows between vertices, is called an undirected graph ; the second picture with arrows is called a directed graph . If you start from a vertex and return to itself after a certain path, it is called a loop . The numbers on each path in Figure 3 are called weights , and the weighted graphs are called nets . If two vertices are connected by a certain number of paths, we call it connected ; if any two nodes in the graph are connected, the graph is called a connected graph . For non-connected, the largest connected subgraphs are called connected components . If any two nodes A and B in a directed graph have at least one path from A to B, and at least one path from B to A, such a graph is called a strongly connected graph . A directed graph that is not strongly connected, and the largest subgraph of each strongly connected is called a strongly connected component . First introduce these basic concepts, and then explain the related concepts when they are used later.
Insert picture description here Insert picture description here

Insert picture description here

2. How to store pictures

1. Adjacency matrix storage

Adjacent means that there is an edge between two vertices (the connection of nodes in an undirected graph is called an edge) or an arc (the connection of nodes in a directed graph is called an arc, the end without an arrow is called the arc tail, and the end with an arrow is Called arc head) exists; the
row in the adjacency matrix in the figure below represents a vertex, a column of numbers in the row indicates whether the vertex is adjacent to the vertex of the corresponding column number, the adjacency is 1, otherwise it is 0;
we use the adjacency matrix to store the vertices In addition, you can use an array to store the value of each node.

Insert picture description here

2. Adjacency table storage

The above adjacency matrix is ​​actually used. In order to express the relationship between the vertices, we can also use an array plus a linked list; use an array to store the value of each vertex, and a linked list to store the adjacent vertices.
The adjacency list is suitable for storing directed graphs and undirected graphs.
Insert picture description here

Insert picture description here

3. Cross linked list storage

The cross linked list is more suitable for storing directed graphs. The first position of each linked list becomes the head node. The head node is composed of three blocks. The first block stores the value of the vertex, and the second pointer points to the head node. The point is the node at the arc head, and the third node points to the node with the head node as the arc end. The common nodes in the linked list are shown in Figure 2:
tailvex: represents the vertex position
with the head node as the end of the arc headvex: represents the vertex position with the head node as the arc head
hlink: the next head node is the arc head The node of the vertex
tlink: the node of the next vertex with the head node as the end of the
arc.info: stores information such as weights
Insert picture description here

Insert picture description here
Insert picture description here

4. Adjacent multiple table storage

The adjacency list is more suitable for storing undirected graphs, which is equivalent to a combination of adjacency list and cross-linked list. The structure of the head node is shown in Figure 1, which is consistent with the head node structure of the adjacency list; the structure of ordinary nodes is shown in Figure 2,
which is consistent with the cross-linked list; where:
mark: stores some additional information, such as nodes Whether to be operated
ivex, jvex: the position of the nodes at both ends of the storage edge in the array
ilink: the next node directly related to
ivex jlink: the next node directly related to jvex
info: weight and other information
Insert picture description here

Insert picture description here
Insert picture description here

5. Summary

We talked about four ways to store trees above. The adjacency matrix is ​​a sequence table, which uses a two-dimensional array to represent the adjacency relationship between nodes; the adjacency table uses an array plus a linked list, the array stores the value of the vertices, and the linked list stores The subscript position of its adjacent vertex. It is suitable for storing directed and undirected graphs; the structure of the nodes in the cross linked list is different from the adjacency list. Each node not only points to the next node in the linked list, but also points to the corresponding nodes in other linked lists, forming multiple crosses . It is suitable for storing directed graphs; for multiple adjacency lists, the head node adopts the structure of adjacency list, and ordinary nodes adopts the structure of a cross-linked list, which is suitable for storing undirected graphs;

3. Depth first search and breadth first search

Relating to the previous tree traversal, depth-first search is similar to pre-order traversal, starting from the root node, and the neighboring points of the later visited vertices are visited first; this is a backtracking idea, assuming that the node has child nodes, then Go to find, if found, continue to find the child node, if not, then return, find the child node of the previous node. Breadth-first search is similar to hierarchical traversal. The vertex that is visited first is visited first.
The following code is implemented in python. The idea is as follows: breadth-first search uses queues to push all nodes in each layer, and then pop them in order And push the child nodes of each node until all elements are accessed. Depth-first search uses iteration, which iteratively traverses the child nodes of each child node until all elements have been traversed.

#-*- coding:utf-8 -*-
from queue import Queue
class node:
    def __init__(self,val):
        self.val = val
        self.next = None
class Traversion:
    def __init__(self,nodes):
        self.peeks = []
        self.visted = [0]*len(nodes)
        self.nodes = nodes
    #广度优先搜索
    def bfs(self):
        #使用队列将需要遍历的节点按顺序压入
        queue = Queue()
        queue.put(0)
        self.visted[0] = 1
        self.peeks.append(self.nodes[0][0])
        while not queue.empty():
            index = queue.get()
            for i in self.nodes[index][1]:
                if self.visted[i] == 0:
                    self.visted[i] = 1
                    self.peeks.append(self.nodes[i][0])
                    queue.put(i)
        return self.peeks
    #对每一层中每一个节点进行递归的访问
    def dfs(self,index):
        self.visted[index] = 1
        self.peeks.append(self.nodes[index][0])
        for i in self.nodes[index][1]:
            if self.visted[i] == 0:
                self.dfs(i)
        return self.peeks
if __name__ == '__main__':
    nodes = [("a", [1, 2, 4]),
                ("b", [2]),
                ("c", [4, 3]),
                ("d", [4]),
                ("e", []),]
    traversion = Traversion(nodes)
    print(traversion.dfs(0))

4. Depth-first spanning tree and breadth-first spanning tree

We now consider how to convert the graph to a tree, so that we can operate the graph in accordance with some tree operations. We consider two generation methods: depth first and breadth first. For undirected graphs, the depth-first spanning tree is a depth-first traversal method, and the tree obtained by recording the vertices passed by the graph is the depth-first spanning tree. Breadth-first spanning tree is to record the vertices that breadth-first traverses to form a tree. For a graph, the occurrence and extension of its nodes are irregular and messy. We express it in the form of a tree, which can make the development of data regular to a certain extent.
For example, for the undirected graph in Fig. 1, the tree generated by depth first is the style of Fig. 2, and the tree generated by breadth first is the style of Fig. 3.
Insert picture description here
Insert picture description here
Insert picture description here
Of course, for non-connected graphs. We use depth first and breadth first to generate a forest composed of multiple trees, which can then be converted into a tree using the child brother notation we mentioned earlier.

5. Minimum spanning tree

Through the previous study, we know that the graph can be converted into a tree, and the depth-first and breadth-first methods can be adopted. But for reality, the optimal meaning is often the minimum spanning tree we will discuss next. Simply put, the minimum spanning tree is the smallest weighted sum of paths in the tree.
We regard the vertices in the graph as cities. Now we need to establish a signal network between these cities. The weight on each side is equivalent to the cost of communication between these two cities. If there are n cities, we Need to build n-1 lines. How to minimize the total cost of these n-1 lines corresponds to our minimum spanning tree.
This is the silver of white flowers! Let's discuss two specific algorithms next, in case of emergency.

1. Prim's algorithm

Primm's algorithm is actually to find the shortest distance between two vertices. The specific process is as follows, first divide the data into A and B categories. A represents the set of vertices that has been determined, and B represents the set of vertices that have not been determined. The initial state A is empty, and B contains all vertices. First randomly select a vertex to add to A, and delete the vertex from B. Then select the nearest vertex in B to the vertex in A, add it to A, and delete the vertex from B. Keep iterating the above process until B is empty.
The time complexity of this algorithm is O(N^2)

2. Kruskal algorithm (Kruskal algorithm)

The Prim's algorithm described above is more suitable for dense connected networks, while the following Kruskal algorithm is more suitable for sparse connected networks. We define dense and sparse as: e<nlog(n), where e represents the edge Number, n represents the number of vertices. The time complexity of the algorithm is the
specific realization idea of elog(e) : first sort all edges according to the weight from small to large, and then traverse the edges. If this edge does not make the tree form a loop, keep it, otherwise delete . Until the number of edges reaches n-1 (we said above that connecting n vertices requires n-1 edges). The summary is to select n-1 edges with the smallest weight and not forming a loop to generate the tree.
So how to judge the loop? We initially assign a different state value to each vertex, and all the vertex states added to the tree are modified to be consistent. In this way, when selecting the next edge, you only need to determine whether the vertices at both ends of the edge are in the same state. If they are consistent, they are already in the tree (a loop will be formed) and discard them, otherwise keep them.

5. Summary

In this article, we first introduce the basic concepts of graphs, such as directed graphs, undirected graphs, connected graphs, and loops. Then it introduces four ways to store graphs. The adjacency matrix is ​​a sequence table and adjacency list is suitable for both directed and undirected graphs; cross linked list is suitable for storing directed graphs, and multiple adjacency lists are suitable for storing undirected graphs. We also introduced depth-first algorithm and breadth-first algorithm, similar to pre-order traversal and level traversal. The depth-first algorithm traverses all the way down the child nodes, and the breadth-first algorithm traverses the sibling node layer. Finally, it introduces how to use depth-first and breadth-first to convert an undirected graph into a tree.

6.Play With Fire

A man lived to 84 years old, suddenly remembered a shameful thing he did when he was young, regretted it, and died because of it. When others see it, they just say that this person does not have any disease and is dead. No one wants to go deep into this matter. People are already dead, and the greatest kindness to the dead is to let his secret die with him. But if those who died weren't really dead, they just ascended to higher dimensions, would it be comforting for us to keep their secrets so much? But what about my own secret? When I am alone, I sometimes do shameful things. Are these all appreciated as movies by those who have died? They wouldn't tell others anyway, so I wouldn't take it seriously. I am not stupid enough to tell others about my shame, but I think the greatest kindness to myself is that no matter how noble I pretend to be in front of the public, I have to understand in my heart that I am just one of thousands of despicable people.

[Marvel/DC/Step on/1080p] High energy ahead! The goose bumps and the visual feast of convergence!

Guess you like

Origin blog.csdn.net/gaobing1993/article/details/108923320