1, Basic ideas
1) Access the specified starting vertex v;
2) From the adjacency point of v which is not visited, the graph is traversed in depth first, until the vertices which have path communication with v are visited;
3) If there are still vertices in the graph that have not been visited at this time, the depth first traversal is carried out again from a vertex that has not been visited until all the vertices in the graph have been visited.
2, Storage structure of Graphs
Adjacency table storage mode of example graph adjacency matrix storage mode of graph
3, Implementation mode
1. Adjacency table
<?php /** * Depth first traversal of Graphs * The storage structure of graph adjacency table */ class Node{ public $value = null; public $next = [];//An array that stores the location of the next node public function __construct($value = null){ $this->value = $value; } } class Graph { // Record whether the node has been traversed public $visited = []; // Adjacency table array of Graphs public $graph = []; /** * Add adjacency points to vertices * @param $vertex Vertex v * @param $adjvex Adjacency point of vertex v */ public function addVertex($vertex, $adjvex) { $this->graph[$vertex][] = $adjvex; } // Convert adjacency list array to adjacency list public function createGraph() { $vertices = array_keys($this->graph); $result = []; foreach ($vertices as $vertex) { $result[$vertex] = new Node($vertex); } foreach ($this->graph as $vertex => $adjvex) { foreach ($adjvex as $v) { if (isset($result[$v]) && is_object($result[$v])) { $result[$vertex]->next[] = $result[$v]; } } } return $result; } /** * recursion * @param $v The first vertex to be accessed is passed in */ public function dfs($v) { // Set visited flag $this->visited[$v] = 1; // Output visited vertex echo $v . PHP_EOL; // print_r($this->graph[$v]);die; for ($i = 0; $i < count($this->graph[$v]); $i++) { if ($this->visited[$this->graph[$v][$i]] == 0) { $this->dfs($this->graph[$v][$i]); } else { continue; } } } /** * non-recursive * @param $v The first vertex to be accessed is passed in */ public function deepFirstSearch($v) { // Initialize node traversal flag $vertices = array_keys($this->graph); foreach ($vertices as $vertex) { $this->visited[$vertex] = 0; } $stack[] = $v; while (!empty($stack)) { $current = array_pop($stack); if ($this->visited[$current->value] == 0) { echo $current->value . PHP_EOL; $this->visited[$current->value] = 1; } for ($i = count($current->next) - 1; $i >= 0; $i--) { if ($this->visited[$current->next[$i]->value] == 0) { $stack[] = $current->next[$i]; } } } } } // test $vertices = ['v1', 'v2', 'v3', 'v4', 'v5', 'v6', 'v7', 'v8']; $g = new Graph(); $g->addVertex('v1', 'v2'); $g->addVertex('v1', 'v3'); $g->addVertex('v2', 'v1'); $g->addVertex('v2', 'v4'); $g->addVertex('v2', 'v5'); $g->addVertex('v3', 'v1'); $g->addVertex('v3', 'v6'); $g->addVertex('v3', 'v7'); $g->addVertex('v4', 'v2'); $g->addVertex('v4', 'v8'); $g->addVertex('v5', 'v2'); $g->addVertex('v5', 'v8'); $g->addVertex('v6', 'v3'); $g->addVertex('v6', 'v7'); $g->addVertex('v7', 'v3'); $g->addVertex('v7', 'v6'); $g->addVertex('v8', 'v4'); $g->addVertex('v8', 'v5'); //print_r($g->graph); // recursion $g->dfs($vertices[0]); // non-recursive $firstVertex = current($g->createGraph()); $g->deepFirstSearch($firstVertex);
2, Adjacency matrix
<?php /** * Depth first traversal of Graphs * The storage structure of graph adjacency matrix */ class Graph { // Storage node information public $vertices; // Storage side information public $arcs; // Number of nodes in a graph public $vexnum; // Record whether the node has been traversed public $visited = []; // initialization public function __construct($vertices) { $this->vertices = $vertices; $this->vexnum = count($this->vertices); for ($i = 0; $i < $this->vexnum; $i++) { for ($j = 0; $j < $this->vexnum; $j++) { $this->arcs[$i][$j] = 0; } } } // Add an edge between two vertices(Undirected graph) public function addEdge($a, $b) { if ($a == $b) { // The head and tail of an edge cannot be the same node return; } $this->arcs[$a][$b] = 1; $this->arcs[$b][$a] = 1; } // From the i Nodes start depth first traversal public function traverse($i) { // Mark the i Nodes traversed $this->visited[$i] = 1; // Print the currently traversed node echo $this->vertices[$i] . PHP_EOL; // In ergodic adjacency matrix i Direct connection of nodes for ($j = 0; $j < $this->vexnum ; $j++) { // The target node is directly connected with the current node, and the node has not been accessed yet. Recursion if ($this->arcs[$i][$j] == 1 && $this->visited[$j] == 0) { $this->traverse($j); } } } // recursion public function dfs() { // Initialize node traversal flag for ($i = 0; $i < $this->vexnum; $i++) { $this->visited[$i] = 0; } // Start deep traversal from nodes not traversed for ($i = 0; $i < $this->vexnum; $i++) { if ($this->visited[$i] == 0) { // If it is a connected graph, it will only be executed once $this->traverse($i); } } } // non-recursive public function deepFirstSearch() { // Initialize node traversal flag for ($i = 0; $i < $this->vexnum; $i++) { $this->visited[$i] = 0; } $stack = []; for ($i = 0; $i < $this->vexnum; $i++) { if (!$this->visited[$i]) { $stack[] = $i; while (!empty($stack)) { // Out of the stack $curr = array_pop($stack); // If the node has not been traversed, traverse the node and stack the child nodes if ($this->visited[$curr] == 0) { echo $this->vertices[$curr] . PHP_EOL; $this->visited[$curr] = 1; // Non traversal child nodes are pushed for ($j = $this->vexnum - 1; $j >= 0; $j--) { if ($this->arcs[$curr][$j] == 1 && $this->visited[$j] == 0) { $stack[] = $j; } } } } } } } } // test $vertices = ['v1', 'v2', 'v3', 'v4', 'v5', 'v6', 'v7', 'v8']; $graph = new Graph($vertices); $graph->addEdge(0, 1); // v1 v2 $graph->addEdge(0, 2); // v1 v3 $graph->addEdge(1, 3); // v2 v4 $graph->addEdge(1, 4); // v2 v5 $graph->addEdge(2, 5); // v3 v6 $graph->addEdge(2, 6); // v3 v7 $graph->addEdge(4, 7); // v5 v8 $graph->addEdge(3, 7); // v4 v8 // recursion $graph->dfs(); // non-recursive $graph->deepFirstSearch();