depth-first search algorithm

depth-first search algorithm

1. DFS concept

DFS means starting from a vertex v in the graph and traversing the graph along the depth direction first. The basic process is: select an initial vertex, then visit the vertex, traverse from an unvisited adjacent point of the vertex and visit the point, and so on, until all the vertices that can be figured out with the initial vertex are access to. At this time, if there are other unvisited nodes, select the unvisited node and continue the above process.

Assume an undirected graph as shown below:

Its depth-first search process:

First visit node A, then find the points adjacent to node A: B and C, choose B and visit node B, then find the adjacent points A, D, and E that are adjacent to node B, since A It has been visited, so select node D and visit node D, then find node B and node H adjacent to node D, since node B has been visited, select node H and visit node H, and then find the points D and E adjacent to the node H. Since D has been visited, select the node E and visit the node E, and find the points B and H adjacent to the node E, but this Both points have been visited, so return along the original path: H->D-b->A, when the search returns to node A, find nodes B and C adjacent to A, because C is not visit, so continue to select node C and visit node C, and so on, gradually visit the undirected graph. The green line in the figure below represents the order of points visited step-by-step during a deep search, and the dashed line represents the path returned by the search during a recursive call.

After the above analysis, traversing the graph is the process of finding the adjacent vertices of the nodes in the graph.


2. Realize

2.1 Non-recursive implementation

Idea: First initialize the access flag array visited[n] = false, then start from the vertex of the graph, visit the vertex and pop the vertex, and use the stack to push all the adjacent nodes of the current vertex into the stack. Then remove the top element from the stack and access the top element, and then push all the adjoining points of the top element onto the stack. Repeat the process continuously.

Status DFSTraverse(ALGraph G){
	//non-recursive form
	stack<int> S;

	for(int i = 0; i<G.vertexNum; i++) visited[i] = false;

	for(int v = 0; v<G.vertexNum; v++){
		if(!visited[v]){
			S.push(v);
			while(!S.empty()){
				int u = S.top ();
				S.pop();
				if(!visited[u]){
					visited[u] = true;
					cout<<"node: "<<G.vertices[u].data<<" ";
				}
				for(int w = FirstAdjVex(G,u); w>= 0; w = NextAdjVex(G, u, w)){
					S.push(w);
				}
			}
		}
	}
	return 1;
}

2.2 Recursive implementation

Idea: First initialize the access tag array visited[n]=false. Starting from a vertex in the graph, visit the node and mark it as being visited, then recursively visit the adjacent nodes of the vertex and mark it as being visited.

void DFS(ALGraph G, int j){
	visited[j] = true;
	cout<<"node: "<<G.vertices[j].data<<" ";
	for(int k = FirstAdjVex(G, j); k>=0; k = NextAdjVex(G, j, k)){
		if(!visited[k])
			DFS(G, k);// For all nodes of node j that have not been visited, continue to recursively call
	}
}

Status DFSTraverse1(ALGraph G){
	//recursive
	for(int i = 0;i<G.vertexNum; i++) visited[i] = false;
	for(int j = 0;j<G.vertexNum; j++)
		if(!visited[j])
			DFS(G,j);
	return 1;
}
The recursive calling process in the above figure:

3. All code

Note: In this code, the graph is stored as an adjacency list. In addition, there are different orders for depth-first search of a graph.
#include "stdafx.h"
#include <iostream>
#include <string>
#include <queue>
#include <stack>

#define MAX_VERTEX_NUM 20

using namespace std;

typedef int infoType;//Arc info
typedef char vertexType;//Vertex save character information
typedef int Status;

typedef struct ArcNode{
	int adjvex;
	struct ArcNode *nextArc;
	infoType *info;
}ArcNode;

typedef struct VertexNode{
	vertexType data;
	ArcNode *firstArc;
}VertexNode, AdjList[MAX_VERTEX_NUM];

typedef struct ALGraph{
	AdjList vertices;
	int vertexNum, arcNum;
	string kind;
}ALGraph;

int locateNode(ALGraph &G, VertexNode node){
	for(int i=0; i<G.vertexNum;i++){
		if(node.data == G.vertices[i].data)
			return i;
	}
	return -1;
}

void insertArcAction(ALGraph &G, int nodeNum1, int nodeNum2);
Status insertArc(ALGraph &G, VertexNode node1, VertexNode node2);

Status createGraph(ALGraph &G, string kind, int vertexNum, int arcNum){
	//Construct a graph using an adjacency list (directed or undirected)
	G.kind = kind;

	G.vertexNum = vertexNum;
	G.arcNum = arcNum;
	
	//Initialize vertex information
	for(int i = 0; i<G.vertexNum; i++){
		cin>>G.vertices[i].data;
		G.vertices[i].firstArc = NULL;
	}

	cout<<"Try to input arcs info"<<endl;
	for(int j = 0; j<G.arcNum; j++){
		cout<<"please input two nodes of "<<j+1<<"-th arc"<<endl;

		VertexNode node1, node2;
		cin>>node1.data>>node2.data;
		insertArc(G, node1, node2);
	}
	return 1;
}

void insertArcAction(ALGraph &G, int nodeNum1, int nodeNum2){
	ArcNode * p;
	ArcNode *arc;

	arc = new ArcNode[1];
	arc->adjvex = nodeNum2;

	p = G.vertices[nodeNum1].firstArc;//Equivalent to the insertion of a linked list
	if(!p){
		G.vertices[nodeNum1].firstArc = arc;
		arc->nextArc = NULL;
	}
	else{
		G.vertices[nodeNum1].firstArc = arc;
		arc->nextArc = p;
	}
}

Status insertArc(ALGraph &G, VertexNode node1, VertexNode node2){
	int nodeNum1 = locateNode(G, node1);//i and j represent the position in AdjList[MAX_VERTEX_NUM]
	int nodeNum2 = locateNode(G, node2);
	if(nodeNum1<0 || nodeNum2<0) exit(-1);
	
	if(G.kind == "DG")
		insertArcAction(G, nodeNum1, nodeNum2);
	else{
		insertArcAction(G, nodeNum1, nodeNum2);
		insertArcAction(G, nodeNum2, nodeNum1);
	}
	return 1;
}

Status printALGraph(ALGraph &G){
	for(int i = 0; i<G.vertexNum; i++){
		cout<<i<<" "<<G.vertices[i].data;
		ArcNode *arc = G.vertices[i].firstArc;

		while(arc){
			cout<<"-->"<<arc->adjvex;
			arc = arc->nextArc;
		}
		cout<<"-->NULL"<<endl;
	}
	return 1;
}

bool visited[MAX_VERTEX_NUM];

int FirstAdjVex(ALGraph G, int j){
	ArcNode *firstArc = G.vertices[j].firstArc;
	if(firstArc)
		return (firstArc->adjvex);
	else
		return -1;
}

int NextAdjVex(ALGraph G, int j, int k){
	ArcNode *firstArc = G.vertices[j].firstArc;
	ArcNode *cur = firstArc;

	if(!firstArc)
		return -1;
	else{
		while(cur){
			if(cur->adjvex == k)
				break;
			cur = cur->nextArc;
		}
	}
	if(cur->nextArc)
		return (cur->nextArc->adjvex);
	else
		return -1;
}

Status DFSTraverse(ALGraph G){
	//non-recursive form
	stack<int> S;

	for(int i = 0; i<G.vertexNum; i++) visited[i] = false;

	for(int v = 0; v<G.vertexNum; v++){
		if(!visited[v]){
			S.push(v);
			while(!S.empty()){
				int u = S.top ();
				S.pop();
				if(!visited[u]){
					visited[u] = true;
					cout<<"node: "<<G.vertices[u].data<<" ";
				}
				for(int w = FirstAdjVex(G,u); w>= 0; w = NextAdjVex(G, u, w)){
					S.push(w);
				}
			}
		}
	}
	return 1;
}

void DFS(ALGraph G, int j){
	visited[j] = true;
	cout<<"node: "<<G.vertices[j].data<<" ";
	for(int k = FirstAdjVex(G, j); k>=0; k = NextAdjVex(G, j, k)){
		if(!visited[k])
			DFS(G, k);
	}
}

Status DFSTraverse1(ALGraph G){
	// recursive form deep-first access tree
	for(int i = 0;i<G.vertexNum; i++) visited[i] = false;
	for(int j = 0;j<G.vertexNum; j++)
		if(!visited[j])
			DFS(G,j);
	return 1;
}

int _tmain(int argc, _TCHAR* argv[])
{
	ALGraph G;
	string kind = "UDG";
	int vertexNum = 9;
	int arcNum = 9;

	cout<<"Try to create a Adjacency list Graph ..."<<endl;
	createGraph(G, kind, vertexNum, arcNum);
	
	cout<<"Try to print a Adjacence list Graph ..."<<endl;
	printALGraph(G);

	cout<<"Try to traverse a undigraph in a regular form..."<<endl;//非递归
	DFSTraverse(G);

	cout<<"Try to traverse a undigraph in a iterational form..."<<endl;//递归
	DFSTraverse1(G);

	system("pause");
	return 0;
}


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325727144&siteId=291194637