其他分享
首页 > 其他分享> > 图论简介及深度优先遍历和广度优先遍历实现

图论简介及深度优先遍历和广度优先遍历实现

作者:互联网

图论简介

图论简介

图的定义

图G =(V,E),V是顶点的又穷非空集合,E是边集合。
V(G)和E(G)分别表示G的顶点集合和边集合。其中,E(G)可以为空集。
若E(G)为有向边的集合,则G为有向图,反之为无向图。
<x,y>表示有向图的边,称之为弧,x为起点,y为终点。(x,y)表示无向图的边,没有特定方向。

图的基本术语

n表示图中的顶点数,e表示边的数目。
(1)子图:G=(V,E)和G’=(V’,E’),如果V’、E’都分别含于V、E,则G’是G的子图。

(2)无向完全图和有向完全图:对于无向图,若有n(n-1)/2条边,则成为无向完全图;对于有向完全图,若有n(n-1)条弧,则称为有向完全图。

(3)稀疏图和稠密图:区分关键在于
e < n l o g 2 n ? e<nlog_2n\quad? e<nlog2​n?
(4)权和网:带权的图称为网,权值可以标在边上。

(5)邻接点:顶点v和v’如果存在一边/弧,则成为v和v’互为邻接点/相关联。

(6)度、入度和出度:顶点v的度是指和v相关联的边数,记为TD(v)。对有向图而言,还有入度和出度的概念,入度表示以v为头的弧的数目,出度表示以v为尾的弧的数目。

(7)连通,连通图,连通分量:连通,两顶点之间有路径即连通,任意两顶点均存在路径即连通图,非连通图可以有连通分量。

(8)强连通图:对有向图而言。

图的类型定义及实现–基于邻接矩阵表示法

邻接矩阵表示法

A [ i ] [ j ] = { 1 若 < v i , v j > 或 ( v i , v j ) ∈ E 0 反 之 A[i][j]= \begin{cases} 1\qquad若<v_i,v_j>或(v_i,v_j)\in E\\ 0\qquad反之 \end{cases} A[i][j]={1若<vi​,vj​>或(vi​,vj​)∈E0反之​

A [ i ] [ j ] = { w i , j 若 < v i , v j > 或 ( v i , v j ) ∈ E ∞ 反 之 A[i][j]= \begin{cases} w_{i,j}\qquad若<v_i,v_j>或(v_i,v_j)\in E\\ \infty\qquad反之 \end{cases} A[i][j]={wi,j​若<vi​,vj​>或(vi​,vj​)∈E∞反之​

#define MAXVEX 20
#define INFINITY 32768

typedef char VertexType; /* 顶点类型应由用户定义  */
typedef int EdgeType; /* 边上的权值类型应由用户定义 */
typedef struct MyGraph
{
	VertexType vexs[MAXVEX]; /* 顶点表 */
	EdgeType arc[MAXVEX][MAXVEX];/* 邻接矩阵,可看作边表 */
	int numNodes, numEdges; /* 图中当前的顶点数和边数  */
}MyGraph;

图的基本操作

Status CreatUDN(MyGraph& G)
{
	cout << "输入总顶点数,总边数,以空格或回车隔开" << endl;
	cin >> G.numNodes >> G.numEdges;
	cout << "依次输入顶点的信息" << endl;
	for (int i = 0; i < G.numNodes; i++)
		cin >> G.vexs[i];
	//初始化邻接矩阵,将权值均置为极大值
	for (int i = 0; i < G.numNodes; i++)
		for (int j = 0; j < G.numNodes; j++)
			G.arc[i][j] = INFINITY;	//如果是图,INFINITY置0即可
	cout << "输入一条边依附的顶点及权值" << endl;
	for (int k = 0; k < G.numEdges; k++)
	{
		VertexType v1, v2;
		EdgeType w;
		cin >> v1 >> v2 >> w;
		int i = LocateVex(G, v1), j = LocateVex(G, v2);
		G.arc[i][j] = w;			//如果是图,赋值为1即可
		G.arc[j][i] = G.arc[i][j];	//如果是有向网或有向图,注掉此行即可
	}
	return OK;
}
int LocateVex(MyGraph G,VertexType u)
{
	for (int i = 0; i < G.numNodes; i++)
		if (u == G.vexs[i])
			return i;
	return -1;
}
int FirstAdjVex(MyGraph G, int v)
{
	for (int i = 0; i < G.numNodes; i++)
	{
		if (G.arc[v][i] != INFINITY)
			return i;
	}
	return -1;
}
int NextAdjVex(MyGraph G, int v, int w)
{
	for (int i = w + 1; i < G.numNodes; i++)
	{
		if (G.arc[v][i] != INFINITY)
			return i;
	}
	return -1;
}

图的深度优先遍历

算法简介

算法实现

//连通图
void DFS(MyGraph G, int v)
{
	cout << G.vexs[v]; visited[v] = true;
	for (int w = FirstAdjVex(G, v); w >= 0; w = NextAdjVex(G, v, w))
	{
		if (!visited[w])
			DFS(G, w);
	}
}
//非连通图
void DFSTraverse(MyGraph G)
{
	for (int v = 0; v < G.numNodes; v++)
	{
		visited[v] = false;
	}
	for (int v = 0; v < G.numNodes; v++)
	{
		if (!visited[v])
			DFS(G,v);
	}
}
//邻接矩阵
void DFSMyGraph(MyGraph G, int v)
{
	for (int v = 0; v < G.numNodes; v++)
	{
		visited[v] = false;
	}
	cout << G.vexs[v]; visited[v] = true;
	for (int w = 0; w < G.numNodes; w++)
	{
		if ((G.arc[v][w] != INFINITY) && (!visited[w]))
			DFS(G, w);
	}
}

图的广度优先遍历

算法简介

算法实现

//对于连通图
void BFS(MyGraph G, int v)
{
	MySqQueue Q;
	for (int v = 0; v < G.numNodes; v++)
	{
		visited[v] = false;
	}
	cout << G.vexs[v]; visited[v] = true;
	InitQueue(Q);
	EnQueue(Q, v);
	while (!QueueEmpty(Q))
	{
		int u;
		DeQueue(Q, u);
		for (int w = FirstAdjVex(G, u); w >= 0; w = NextAdjVex(G, u, w))
		{
			if (!visited[w])
			{
				cout << G.vexs[w]; visited[w] = true;
				EnQueue(Q, w);
			}
		}
	}
}
//对于非连通图
void BFSTraverse(MyGraph G)
{
	for (int v = 0; v < G.numNodes; v++)
	{
		visited[v] = false;
	}
	for (int v = 0; v < G.numNodes; v++)
	{
		if (!visited[v])
			BFS(G, v);
	}
}
//邻接矩阵
void BFSMyGraph(MyGraph G, int v)
{
	for (int v = 0; v < G.numNodes; v++)
	{
		visited[v] = false;
	}
	BFS(G, w);
}

BFS和DFS实验验证

#include "Graph.h"
MyGraph graph;
int main()
{
	CreatUDN(graph);
	PrintfUDN(graph);
	system("pause");
	cout << "逐节点深度优先遍历:" << endl;
	for (int i = 0; i < graph.numNodes; i++)
	{
		cout << "\n以节点"<<graph.vexs[i]<<"开始" << endl;
		DFSMyGraph(graph, i);
	}
	system("pause");
	DFSTraverse(graph);
	system("pause");
	cout << "逐节点广度优先遍历:" << endl;
	for (int i = 0; i < graph.numNodes; i++)
	{
		cout << "\n以节点" << graph.vexs[i] << "开始" << endl;
		BFSMyGraph(graph,i);
	}
	system("pause");
	BFSTraverse(graph);
	system("pause");
}

在这里插入图片描述

标签:优先,遍历,连通,numNodes,int,图论,邻接矩阵,++,顶点
来源: https://blog.csdn.net/Brid_ger/article/details/120241874