【Data structure and algorithm】Graph traversal (depth-first traversal DFS algorithm)

1.1 Depth-first traversal

 Depth-first traversal (depth first search), also known as depth-first search or DFS for short. Its main idea is, for example, to find a key. For example: one of our car keys is lost, but it is certain that it must be somewhere in the house, so we need to start looking for it from the room, but should we look for it in a certain part of the room or the whole room Where to find another room after searching? Depth-first traversal means searching all the places in a room before searching other rooms until the car key is found.

Suppose you need to complete a task now. You need to know that you are in the following maze. Starting from vertex A, you have to go through all the vertices in the graph and mark them. Note that you are not simply walking by looking at such a planar graph, but walking in the same way as in reality. Complete the task in the maze.

Obviously, we need a strategy for traversing this kind of graph, otherwise it is easy to get lost in this extensive road, and we can only rely on luck to complete the task. If you have a certain understanding of depth-first traversal after reading this article, this task is not difficult to complete.

First of all, we start from point A, and after making a mark indicating that we have passed, there are two roads in front of us, leading to B and F. We set a principle for ourselves, in the case of no repeated vertices, always go to Walk on the right, so we have reached the B vertex. The process of the whole path can be referred to the figure below. At this time, there will be three forks, leading to C, I, and G. With the right hand, we have reached the C vertex. After going all the way to the F vertex, when we found the next one, we returned to the A vertex. At the F vertex, we took the second-to-last passage on the right hand to the G vertex, and encountered three more roads, but found B, D We have already walked through, so we reached the H vertex. When we reached H, we encountered two intersections that we both walked through, but we clearly knew that we had not completed the traversal of the graph, so we retreated all the way from H to G, F, E , D vertex, when I reach D vertex, I find that I have not walked through it, so I walk to I, and this task is completed.

 

In fact, from the above description, depth-first traversal is a recursive process. If you look carefully, you will find that it is like a pre-order traversal of a tree. It starts from a certain vertex V in the graph, visits the vertex, and then traverses the graph in depth first from the unvisited adjacent points of V until all the vertices in the graph that have paths with V are visited.

The code for the depth traversal of the adjacency matrix is ​​as follows:

int visited[10]; 
//邻接矩阵的深度优先递归算法
void DFS(struct photo* G, int i)        //访问标志的数组
{
	int j;
	visited[i] = 1;
	cout << G->vex[i]<<" ";        //打印结点的内容
	for (j = 0; j < G->numnodes; j++)
	{
		if (G->arc[i][j] == 1 && visited[j] == 0)    //对未被访问的结点进行递归
			DFS(G, j);
	}
}
//邻接矩阵的深度遍历操作
void DFStraverse(struct photo* G)
{
	int i;
	for (i = 0; i < G->numnodes; i++)
		visited[i] = 0;        //初始化标志数组都为被访问
	for (i = 0; i < G->numnodes; i++)
		if (visited[i] == 0)
			DFS(G, i);        //对未被党文的顶点调用DFS
}

The overall runnable code is as follows, including how to store data:

struct photo
{
	char vex[10];
	int arc[10][10]={0};
	int numnodes, numdges;
};

void creategraph(struct photo*G)
{
	cout << "请输入顶点数和边数:" << endl;
	cin >> G->numnodes >> G->numdges;
	for (int i = 0; i < G->numnodes; i++)
		cin >> G->vex[i];
	for (int i = 0; i < G->numnodes; i++)
		for (int j = 0; j < G->numnodes; j++)
			G->arc[i][j] = 0;
	for (int k = 0; k < G->numdges; k++)
	{
		int i, j;
		cout << "请输入有边点数:(i,j)" << endl;
		cin >> i>>j;
		G->arc[i][j] = 1;
		G->arc[j][i] = G->arc[i][j];
	}
}

void print(struct photo* G)
{
	for (int i = 0; i < G->numnodes; i++)
	{
		for (int j = 0; j < G->numnodes; j++)
		{
			cout <<setw(2)<< G->arc[i][j] << " ";
		}
		cout << endl;
	}
}

int visited[10]; 
void DFS(struct photo* G, int i)
{
	int j;
	visited[i] = 1;
	cout << G->vex[i]<<" ";
	for (j = 0; j < G->numnodes; j++)
	{
		if (G->arc[i][j] == 1 && visited[j] == 0)
			DFS(G, j);
	}
}

void DFStraverse(struct photo* G)
{
	int i;
	for (i = 0; i < G->numnodes; i++)
		visited[i] = 0;
	for (i = 0; i < G->numnodes; i++)
		if (visited[i] == 0)
			DFS(G, i);
}
int main()
{
	struct photo* y;
	y = (struct photo*)malloc(sizeof(struct photo));
	creategraph(y);
	print(y);
	DFStraverse(y);
	return 0;
}

The general running results are as follows. According to the inferences mentioned above, the data I entered in the figure below can be deduced, mainly to observe and master this idea:

The code of the adjacency list The code of the DFStraverse function is almost exactly the same, but in the recursive function, it is different because the storage structure is changed from an array to a linked list.

The code for deep traversal of the adjacency list is as follows:

 

int visited[10];
void DFS(nodes* G, int i)
{
	struct dege* e;
	visited[i] = 1;
	cout << G->adj[i].data<<" ";
	e = G->adj[i].first;
	while (e)
	{
		if (visited[e->adv] == 0)
			DFS(G, e->adv);
		e = e->next;
	}
}
void DFStraverse(nodes* G)
{
	for (int i = 0; i < G->numnodes; i++)
		visited[i] = 0;
	for (int i = 0; i < G->numnodes; i++)
		if (visited[i] == 0)
			DFS(G, i);
}

The code for creating a complete adjacency list and depth-first traversal is as follows:

struct dege
{
	int adv;
	struct dege* next;
};

typedef struct vex
{
	char data;
	struct dege* first;
}adjlist[100];

struct nodes
{
	adjlist adj;
	int numnodes, numedges;
};

void create(struct nodes* G)
{
	struct dege* e;
	cout << "请输入顶点数目和边的数目:" << endl;
	cin >> G->numnodes >> G->numedges;
	for (int i = 0; i < G->numnodes; i++)
	{
		cin >> G->adj[i].data;
		G->adj[i].first = NULL;
	}
	for (int k = 0; k < G->numedges; k++)
	{
		cout << "请输入有边的结点i,j:" << endl;
		int i, j;
		cin >> i >> j;
		e = (struct dege*)malloc(sizeof(struct dege));
		e->adv = j;
		e->next = G->adj[i].first;
		G->adj[i].first = e;
		e = (struct dege*)malloc(sizeof(struct dege));
		e->adv = i;
		e->next = G->adj[j].first;
		G->adj[j].first = e;
	}
}

int visited[10];
void DFS(nodes* G, int i)
{
	struct dege* e;
	visited[i] = 1;
	cout << G->adj[i].data<<" ";
	e = G->adj[i].first;
	while (e)
	{
		if (visited[e->adv] == 0)
			DFS(G, e->adv);
		e = e->next;
	}
}
void DFStraverse(nodes* G)
{
	for (int i = 0; i < G->numnodes; i++)
		visited[i] = 0;
	for (int i = 0; i < G->numnodes; i++)
		if (visited[i] == 0)
			DFS(G, i);
}
int main()
{
	struct nodes* S;
	S = (struct nodes*)malloc(sizeof(struct nodes));
	create(S);
	DFStraverse(S);
	return 0;
}

The final running result is as follows:

I have been a little confused these days, mainly because the midterm exam review has disrupted my own review plan.

I like a saying very much: teenagers don't want to climb high, but want to be safe and healthy. 

Guess you like

Origin blog.csdn.net/m0_61886762/article/details/124742616