12.11数据结构-图

无向完全图 :在无向图中,如果任意两个顶点之间都存在 则称该图为无向完全图。

向完全图 :在有向图中,如果任意两个顶点之间都存在方向相反的两条弧, 则称该图为有向完全图。

含有 n 个顶点的无向完全图有 n ×(n-1)/2 条边。

含有 n 个顶点的有向完全图有 n ×(n-1) 条边。

顶点的度: 无向 图中,顶点 v 是指依附于该顶点的边数,通常记为TD (v)。

顶点的入度: 有向 图中,顶点 v 入度 是指以该顶点为 弧头 的弧的数目, 记为 ID (v)

顶点 出度: 有向 图中,顶点 v 出度 是指以该顶点为 弧尾 的弧的数目,记为 OD (v)

在具有 n 个顶点、 e 条边的无向图G中,各顶点的度之和与边数之和的关系:

在具有 n 个顶点、 e 条边的有向图 G 中,各顶点的入度之和与各顶点的出度之和的关系?与边数之和的关系:

回路(环) :第一个顶点和最后一个顶点相同的路径。

简单路径: 序列中顶点不重复出现的路径。

简单回路(简单环): 除了第一个顶点和最后一个顶点外,其余顶点不重复出现的回路。

子图: 若图 G =( V E ), G' =( V' E' ), 如果 : V' Í V E' Í E 则称图 G' G 的子图。

连通图: 在无向图中,如果从一个顶点 v i 到另一个顶点 v j ( i j ) 有路径,则称顶点 v i v j 是连通的。如果图中任意两个顶点都是连通的,则称该图是连通 图。

连通分量: 非连通图的极大连通子图称为连通分量。

一个 n 个顶点的连通 无向图 ,其边的个数至少为( n-1 )

因为它如果是个树的话,边就最少了

连通(Connected)

  • 无向图中的连通:在无向图中,如果任意两个顶点之间存在一条路径,那么这个图就是连通的。即从一个顶点出发,可以通过边访问到任何其他顶点。

  • 有向图中的连通:在有向图中,如果从任意两个顶点中的一个可以通过有向边到达另一个,那么这两个顶点是连通的。但需要注意,这并不意味着整个图是连通的,仅是针对特定的顶点。

强连通(Strongly Connected)

  • 有向图中的强连通:在有向图中,如果图中的每一对顶点 都能相互到达,那么这个图是强连通的。强连通要求顶点之间的路径是双向的。

  • 对于无向图,强连通的概念并不适用,因为无向图的每条边本身就是双向的,通常直接称为"连通"。

总结

  • 连通:在无向图中,任意两个顶点都有路径相连;在有向图中,特定的两个顶点之间有一条路径。
  • 强连通:仅适用于有向图,表示任意两个顶点之间既可以从一个到达另一个,也可以从另一个到达前者。

要连通具有 n 个顶点的 有向图 ,至少需要( n-1 )条边。

只要连通就行,不用强连通。所以画个单边的树就行

由握手定理知A正确,

在无向图中,握手定理表述为:所有顶点的度数之和等于边数的 2 倍。

通俗来讲,假如把图中的顶点看成是人,边看成是两个人握手,那么每个人握手的次数(即顶点的度数)加起来,就等于总的握手次数的 2 倍,因为每一条边(一次握手)会在两个顶点(两个人)的度数中各被计算一次。

BC错误,画个单边树,得到b错误,画个三角形得到c错误。

图的遍历

① 在图中,如何选取遍历的 起始 顶点?

中,任何两个顶点之间都可能存在边,顶点是没有确定的先后次序的,所以,顶点的编号不唯一。 为了定义操作的方便,将图中的顶点按任意顺序排列起来,比如,按顶点的 存储顺序 。然后选取下标小的顶点

② 从某个起点始可能 到达不了 所有 其它顶点 怎么办?

解决方案:多次调用从某顶点出发遍历图的算法。

③ 因图中可能存在回路,某些顶点可能会被重复访问,那么如何 避免 遍历不会因回路而陷入 死循环 ?

解决方案:附设访问标志数组 visited[n]

④ 在图中,一个顶点可以和其它多个顶点相连,当这样的顶点 访问过后,如何选取 下一个 要访问的顶点?

解决方案: 深度 优先遍历和 广度 优先遍历。

邻接矩阵的DFS和BFS:

cpp 复制代码
#include<iostream>
using namespace std;
int visited[10] = { 0 };

class MGraph
{
public:
	MGraph(char a[], int n, int e);
	~MGraph() {};
	void DFS(int v);
	void BFS(int v);
private:
	char vertex[10];
	int edge[10][10];
	int vertexNum, edgeNum;

};

MGraph::MGraph(char a[], int n, int e)
{
	int i, j, k;
	vertexNum = n;
	edgeNum = e;
	for (i = 0; i < vertexNum; i++)
		vertex[i] = a[i];
	for (i = 0; i < vertexNum; i++)
		for (j = 0; j < vertexNum; j++)
			edge[i][j] = 0;
	for (k = 0; k < edgeNum; k++)
	{
		cin >> i >> j;
		edge[i][j] = 1;
		edge[j][i] = 1;
	}
}

void MGraph::DFS(int v)
{
	int  j;
	cout << vertex[v];
	visited[v] = 1;
	for(j =0;j<vertexNum;j++)
		if (edge[v][j] == 1 && visited[j] == 0)
			DFS(j);
}

void MGraph::BFS(int v)
{
	cout << vertex[v];
	visited[v] = 1;
	int w, j, Q[10];
	int front = -1, rear = -1;
	Q[++rear] = v;
	while (front != rear)
	{
		w = Q[++front];
		for(j = 0;j<vertexNum;j++)
			if (edge[w][j] == 1 && visited[j] == 0)
			{
				cout << vertex[j];
				visited[j] = 1;
				Q[++rear] = j;
			}
	}
}

int main()
{
	int i;
	char ch[] = { 'A','B','C','D','E' };
	MGraph MG(ch, 5, 6);
	for (i = 0; i < 10; i++)
		visited[i] = 0;
	cout << "深搜:" << endl;
	MG.DFS(0);
	for (i = 0; i < 10; i++)
		visited[i] = 0;
	cout << endl;
	cout << "广搜" << endl;
	MG.BFS(0);
}

邻接表:

cpp 复制代码
#include<iostream>
using namespace std;
int visited[10] = { 0 };

struct EdgeNode
{
	int adjvex;
	EdgeNode* next;
};

struct VertexNode
{
	char vertex;
	EdgeNode* firstEdge;
};

class ALGraph
{
public:
	ALGraph(char a[], int n, int e);
	~ALGraph() ;
	void DFS(int v);
	void BFS(int v);
private:
	VertexNode adjlist[10];
	int vertexNum, edgeNum;
};

ALGraph::ALGraph(char a[], int n, int e)
{
	int i, j, k;
	EdgeNode* s = nullptr;
	vertexNum = n;
	edgeNum = e;
	for (i = 0; i < vertexNum; i++)
	{
		adjlist[i].vertex = a[i];
		adjlist[i].firstEdge = nullptr;
	}
	for (k = 0; k < edgeNum; k++)
	{
		cin >> i >> j;
		s = new EdgeNode;
		s->adjvex = j;
		s->next = adjlist[i].firstEdge;
		adjlist[i].firstEdge = s;
	}
}

ALGraph::~ALGraph()
{
	EdgeNode* p = nullptr, * q = nullptr;
	for (int i = 0; i < vertexNum; i++)
	{
		p = q = adjlist[i].firstEdge;
		while (p != nullptr)
		{
			p = p->next;
			delete q;
			q = p;
		}
	}
}

void ALGraph::DFS(int v)
{
	int j;
	EdgeNode* p = nullptr;
	cout << adjlist[v].vertex;
	visited[v] = 1;
	p = adjlist[v].firstEdge;
	while (p != nullptr)
	{
		j = p->adjvex;
		if (visited[j] == 0)
			DFS(j);
		p = p->next;
	}
}

void ALGraph::BFS(int v)
{
	int w, j, Q[10];
	int front = -1, rear = -1;
	EdgeNode* p = nullptr;
	cout << adjlist[v].vertex;
	visited[v] = 1;
	Q[++rear] = v;
	while (front != rear)
	{
		w = Q[++front];
		p = adjlist[w].firstEdge;
		while (p != nullptr)
		{
			j = p->adjvex;
			if (visited[j] == 0)
			{
				cout << adjlist[j].vertex;
				visited[j] = 1;
				Q[++rear] = j;
			}
			p = p->next;
		}
	}
}

int main()
{
	int i;
	char ch[] = { 'A','B','C','D','E' };
	ALGraph ALG(ch, 5, 6);
	ALG.DFS(0);
	for (i = 0; i < 10; i++)
		visited[i] = 0;
	cout << endl;
	ALG.BFS(0);
}
相关推荐
迅猛龙办公室14 分钟前
C语言——实现矩阵转置
c语言·算法·矩阵
带多刺的玫瑰23 分钟前
Leecode刷题C语言之k次乘运算后的数组②
c语言·数据结构·算法
notfindjob28 分钟前
sqlite加密-QtCipherSqlitePlugin 下
数据库·算法·sqlite
凡人的AI工具箱29 分钟前
每天40分玩转Django:Django部署
数据库·后端·python·算法·django
ChoSeitaku35 分钟前
图的基本概念|存储
算法·图论
殇淋狱陌43 分钟前
第三章 列表(List)语法讲解
数据结构·python·学习·数据分析·list
yoyobravery1 小时前
矩阵的基本知识
c语言·数据结构·算法·矩阵
IT古董1 小时前
【漫话机器学习系列】010.Bagging算法(Bootstrap Aggregating)
人工智能·算法·机器学习·bootstrap
hahahahanhanhan1 小时前
leetcode刷题——贪心算法
算法·leetcode·贪心算法
aaal12341 小时前
代码随想录算法训练营day46|动态规划part12
算法·动态规划