现在的位置: 首页 > 综合 > 正文

图的深度遍历

2018年02月15日 ⁄ 综合 ⁄ 共 3501字 ⁄ 字号 评论关闭

图的深度遍历(Depth First Serch),即DFS。采用递归方法。如果当前顶点有一下层节点则没有被访问过,则访问,否则回溯。

下面动画,展示了DFS算法的具体过程。

DFS

代码如下

//TestMGraph.cpp
#include "MatrixGraph.h"

#define DefA 0
#define DefB 1
#define DefC 2
#define DefD 3
#define DefE 4
#define DefF 5
#define DefG 6
#define DefH 7
#define DefI 8

void CreateGraph1(MatrixGraph & mGraph)
{
	std::vector<char> vertexName;
	char arr[]={'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'};
	vertexName.insert(vertexName.begin(), arr, arr+9);

	std::vector<Edge> edges;
	Edge e;
	//1
	e.weight = 1;
	e.i = DefA;e.j=DefB;
	edges.push_back(e);
	//2
	e.i = DefF;e.j=DefE;
	edges.push_back(e);
	//3
	e.i = DefC;e.j=DefD;
	edges.push_back(e);
	//4
	e.i = DefI;e.j=DefD;
	edges.push_back(e);
	//5
	e.i = DefA;e.j=DefF;
	edges.push_back(e);
	//6
	e.i = DefB;e.j=DefG;
	edges.push_back(e);
	//7
	e.i = DefB;e.j=DefC;
	edges.push_back(e);
	//8
	e.i = DefD;e.j=DefE;
	edges.push_back(e);
	//9
	e.i = DefG;e.j=DefD;
	edges.push_back(e);
	//10
	e.i = DefG;e.j=DefF;
	edges.push_back(e);
	//11
	e.i = DefB;e.j=DefI;
	edges.push_back(e);
	//12
	e.i = DefG;e.j=DefH;
	edges.push_back(e);
	//13
	e.i = DefH;e.j=DefD;
	edges.push_back(e);
	//14
	e.i = DefH;e.j=DefE;
	edges.push_back(e);
	//
	e.i = DefC;e.j=DefI;
	edges.push_back(e);

	CreateMatrixGraph(mGraph, vertexName, edges);
}

void TestMGraph()
{
	MatrixGraph mGraph;
	CreateGraph1(mGraph);
	MDFSTraverse(mGraph, 0);
	//MBFSTraverse(mGraph, 0);
}

 

//MatrixGraph.h
#pragma once
#include <vector>

struct MatrixGraph
{
	enum{MAXVEX=100};
	static const int INFINITY;
	char vexs[MAXVEX]; //顶点类型 char
	int arc[MAXVEX][MAXVEX]; //邻接矩阵
	int numVerteices; //图中当前的顶点数
	int numEdges; //图中当前的边数
	MatrixGraph();
};

void CreateMatrixGraph(MatrixGraph & mGraph, std::vector<char> & vertexName, std::vector<Edge> & edges);
void MDFSTraverse(MatrixGraph & mGraph, int v);

 

//MatrixGraph.cpp
#include "MatrixGraph.h"
#include <iostream>
#include <memory.h>
#include <queue>
const int MatrixGraph::INFINITY = INT_MAX;

bool visited[MatrixGraph::MAXVEX];

MatrixGraph::MatrixGraph()
	:numVerteices(0),
	 numEdges(0)
{
	//temp
	memset(vexs, 0, sizeof(char)*MAXVEX);
	for(int i=0; i<MAXVEX; i++)
	{
		for(int j=0; j<MAXVEX; j++)
		{
			arc[i][j] = INFINITY;
		}
	}

	for(int i=0; i<MAXVEX; i++)
	{
		arc[i][i] = 0;
	}
}



void CreateMatrixGraph(MatrixGraph & mGraph, std::vector<char> & vertexName, std::vector<Edge> & edges)
{
	int count = vertexName.size();
	mGraph.numVerteices = count;

	//生成顶点
	for(int i=0; i<count; i++)
	{
		mGraph.vexs[i] = vertexName[i]; //i为顶点的编号
	}

	//生成边
	count = edges.size(); //一定是偶数
	for(int k=0;k<count; k++)
	{
		mGraph.arc[edges[k].i][edges[k].j] = mGraph.arc[edges[k].j][edges[k].i] = edges[k].weight; //无向图
	}
}

//返回v节点的第一个邻接顶点。若顶点v在图中没有邻接顶点,则返回-1
int FirstAdjVex(MatrixGraph & mGraph, int v)
{
	for(int j=0; j<mGraph.numVerteices; j++)
	{
		//图的边有权重 不相连的边的权重为INFINITY 权重为非负整数
		if(mGraph.arc[v][j] != MatrixGraph::INFINITY && mGraph.arc[v][j] != 0 && !visited[j])
		//if(mGraph.arc[v][j] != MatrixGraph::INFINITY && mGraph.arc[v][j] != 0)
			return j;
	}

	return -1;
}

//返回v的(相对于w的)下一个邻接顶点。若访问完了v的所有顶点,则返回-1
int NextAdjVex(MatrixGraph & mGraph, int v, int w)
{
	for(int j=w; j<mGraph.numVerteices; j++)
	{
		//图的边有权重 不相连的边的权重为INFINITY 权重为非负整数
		if(mGraph.arc[v][j] != MatrixGraph::INFINITY&& !visited[j]) 
		//if(mGraph.arc[v][j] != MatrixGraph::INFINITY) 
		{
			return j;
		}
	}
	return -1;
}

//《结构结构》(c语言版) 严蔚敏
void MDFS(MatrixGraph & mGraph, int v, int parentID)
{
	//从第v个顶点出发递归深度优先遍历图G
	visited[v] = true;
	std::cout<<mGraph.vexs[v] <<":parent="<<mGraph.vexs[parentID]<<std::endl;
	for(int w = FirstAdjVex(mGraph, v); w>-1; w=NextAdjVex(mGraph, v, w))
	{
		if(!visited[w])
			MDFS(mGraph, w, v); //对v的沿未访问的邻接顶点w递归调用DFS
	}
}

void MDFSTraverse(MatrixGraph & mGraph, int v)
{
	memset(visited, 0, sizeof(bool)*MatrixGraph::MAXVEX);
	MDFS(mGraph, v, 0);

}

结果

A:parent=A
B:parent=A
C:parent=B
D:parent=C
E:parent=D
F:parent=E
G:parent=F
H:parent=G
I:parent=D
请按任意键继续. . .

 

随便说一下,代码结构参考《数据结构》(c语言版) 严蔚敏【1】。但【1】中的代码不能从任意一个顶点开始深度遍历。且【1】中的代码可以遍历非连通图,并不是专门为遍历连通图设计的。

给CSDN提个建议:通过CSDN博客上传GIF图片,插入博客中。GIF图片是死图。建议修改成活图。 

抱歉!评论已关闭.