深度优先遍历(邻接矩阵,邻接表)

    深度优先遍历也称为深度优先搜索,简称为DFS。

    深度优先遍历的思路是从图中某个顶点V出发,访问此顶点,然后从V的未被访问过的邻接点出发深度优先遍历图,直到图中所有与V路径相通的顶点都被访问到

    该遍历过程用到递归。

    深度优先遍历用到了一个辅助数组Graph_sign【】,该数组的下标与顶点数组的下标对应,即当Graph_sign【1】中储存的标记为true就表示顶点数组vexs【1】中储存的顶点已被遍历到

代码:

#define _CRT_SECURE_NO_WARNINGS 1
#include
using namespace std;
typedef char VertexType;//顶点类型
typedef int EdgeType;//边上的权值类型
#define MAXVEX 20//最大顶点数(开辟储存顶点的一维数组的空间大小)
#define INFINITY 10000//用10000来代表无穷(在储存边的二维数组中,对没有该边存在的表格,权值设为无穷)
//定义图的结构体(图由储存顶点的一维数组和储存边的二维数组,以及记录图中结点数和边数的int类型的变量组成)
struct MGraph
{
	VertexType vexs[MAXVEX];//储存顶点的一维数组
	EdgeType arc[MAXVEX][MAXVEX];//储存边的二维数组
	int Num_vex, Num_arc;//图中的顶点数和边数
};

//无向网图的创建
void Create_MGraph(MGraph& G)
{
	int m, n;
	cout << "请输入图的顶点数和边数" << endl;
	cin >> G.Num_vex >> G.Num_arc;
	cout << "请依次输入图的顶点:" << endl;
	for (int i = 0; i < G.Num_vex; i++)
	{
		cin >> G.vexs[i];
	}
	//初始化储存边的二维数组
	for (int i = 0; i < G.Num_vex; i++)
		for (int j = 0; j < G.Num_vex; j++)
		{
			G.arc[i][j] = INFINITY;
		}
	//向二维数组中输入对应边的权值
	for (int k = 0; k < G.Num_arc; k++)
	{
		cout << "请依次输入边(Vm,Vn)的下标m,n" << endl;
		cin >> m >> n;
		cout << "请输入边(" << G.vexs[m-1] << "," << G.vexs[n - 1] << ")的权值" << endl;
		cin >> G.arc[m - 1][n - 1];
		//由于是无向网图,所以存在边(m,n),就存在边(n,m)所以我们还应该向二维数组的(n,m)位置输入权值
		G.arc[n - 1][m - 1] = G.arc[m - 1][n - 1];
	}
}

//深度优先遍历输出所有顶点
//记录顶点是否被遍历过的标志数组
bool Graph_sign[MAXVEX];
//邻接矩阵的深度优先算法
void DFS(MGraph& G,int i)//i是作为第一个遍历的顶点的下标
{
	cout << G.vexs[i] << " ";
	//下标为i的顶点已经遍历到改变标志
	Graph_sign[i] = true;
	//遍历其余顶点,判断由顶点i能到达的下一个顶点
	for (int j = 0; j < G.Num_vex; j++)
	{
		if (G.arc[i][j] != INFINITY && !Graph_sign[j])
		{
			DFS(G, j);
		}
	}
}

//邻接矩阵的深度遍历操作
void DFS_MGraph(MGraph& G)
{
	//初始化标志数组
	for (int i = 0; i < G.Num_vex; i++)
	{
		Graph_sign[i] = false;
	}
	//图不连通的情况要有多个顶点作为第一个遍历的顶点
	for (int j = 0; j < G.Num_vex; j++)
	{
		if (!Graph_sign[j])
			DFS(G, j);
	}
}


int main()
{
	MGraph G;
	Create_MGraph(G);
	DFS_MGraph(G);
	system("pause");
	return 0;
}

        邻接表和邻接矩阵大同小异:

代码如下:

#define _CRT_SECURE_NO_WARNINGS 1
#define _CRT_SECURE_NO_WARNINGS 1
#include
using namespace std;
#define MAXSIZE 20
//顶点类型
typedef char VetexType;
//权值类型
typedef int InfoType;
//边表结点
struct EdgeNode
{
	//邻结点域储存顶点的下标
	int adjvex;
	//权值
	InfoType m_info;
	//指向下一个边表结点的指针
	EdgeNode* next;
};

//顶点表结点
struct VertexNode
{
	//顶点
	VetexType vetex;
	//指向边表的头指针
	EdgeNode* FirstEdge;
};

//邻接表
struct GraphAdiList
{
	//顶点数组
	VertexNode Adjext[MAXSIZE];
	//顶点个数,边条数
	int numVertex, numEdges;
};

//创建邻接表
void CreaterADGraph(GraphAdiList& G)
{
	int m, n, info;
	cout << "请输入顶点个数和边条数" << endl;
	cin >> G.numVertex >> G.numEdges;
	//初始化顶点表
	for (int i = 0; i < G.numVertex; i++)
	{
		cout << "请输入第" << i + 1 << "个顶点" << endl;
		//初始化顶点表中的两个属性
		cin >> G.Adjext[i].vetex;
		G.Adjext[i].FirstEdge = NULL;
	}
	//创建边表
	for (int k = 0; k < G.numEdges; k++)
	{
		EdgeNode* p;
		p = new EdgeNode;
		cout << "请输入边(vm,vn)上的顶点序号(m,n)和权值" << endl;
		cin >> m >> n >> info;
		//初始化创建的边表结点p
		p->adjvex = n - 1;
		p->m_info = info;
		//将边表结点p按头插法插入邻接表
		p->next = G.Adjext[m - 1].FirstEdge;
		G.Adjext[m - 1].FirstEdge = p;
		//由于该图是无向图所以还要考虑(n,m)的情况
		p = new EdgeNode;
		p->adjvex = m - 1;
		p->m_info = info;
		p->next = G.Adjext[n - 1].FirstEdge;
		G.Adjext[n - 1].FirstEdge = p;
	}
	cout << "邻接表创建完成" << endl;
}

//深度优先遍历输出所有顶点
//邻接表的深度优先遍历算法
bool Graph_sign[MAXSIZE];//标志数组,用来判断顶点是否被遍历过,被遍历过的为true,否则为false
void DFS(GraphAdiList& G, int i)//i是顶点在顶点表中的下标
{

	//说明下标为i的顶点已经被遍历
	Graph_sign[i] = true;
	cout << G.Adjext[i].vetex;
	EdgeNode* p;
	p = G.Adjext[i].FirstEdge;
	if (!Graph_sign[p->adjvex])
	{
		DFS(G, p->adjvex);
	}
}

//邻接表的深度遍历操作
void ADGraph(GraphAdiList& G)
{
	//初始化标志数组
	for (int i = 0; i < G.numVertex; i++)
	{
		Graph_sign[i] = false;
	}
	//找到未被遍历到的顶点作为第一个遍历的顶点进行遍历(要是图是全部连通的就只会遍历一次)
	for (int j = 0; j < G.numVertex; j++)
	{
		if (!Graph_sign[j])
		{
			DFS(G, j);
		}
	}
}

int main()
{
	GraphAdiList G;
	CreaterADGraph(G);
	ADGraph(G);
}

    以上两个代码都是完整的可调式的程序,相应的关于邻接矩阵和邻接表的创建可以看这里:

邻接表创建,邻结矩阵的创建。

    深度优先遍历的流程图如下:

深度优先遍历(邻接矩阵,邻接表)_第1张图片

 

  ps:以上图来自于大话数据结构

    我们注意到在深度遍历操作中我们还要利用for循环遍历所有顶点,再将其传入深度优先遍历算法DFS中,其实我们的深度优先遍历算法DFS只要传入一个顶点就已经可以遍历完一个连通图了,那为什么我们还要遍历所有顶点判断出没有遍历到的顶点再调用DFS函数呢:-------因为我们的图不一定是连通的,要是图不连通的话就会分为几个连通的部分,而深度优先遍历算法DFS只会遍历出与传入的首个顶点连通的所有顶点,而未与首个顶点连通的顶点是遍历不出来的。所以要再对所有顶点进行遍历,找出其他连通部分的顶点作为该连通部分的首个顶点,传入到DFS算法中

    (若图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点作起始点,重复DFS算法直到图中所有顶点都被访问到为止

    

你可能感兴趣的:(深度优先,算法,数据结构,c++)