一、图介绍
1、定义
图由结点的有穷集合V和边的集合E组成。其中,结点也称为顶点。一对结点(x, y)称为边(edge),表示顶点x连接到顶点y。边可以包含权重/成本,显示从顶点x到y所需的成本。若两个顶点之前存在一条边,就表示这两个顶点具有相邻关系。
2、类型
(1)无向图
(2)有向图
3、表示方法
(1)邻接矩阵
邻接矩阵存储结构就是用矩阵表示图中各顶点之间的邻接关系,两个顶点有邻接关系,就记录为1,否则为0。
(2)邻接表
邻接表是图的一种顺序存储与链式存储相结合的存储方式。
4、遍历方法
(1)广度优先搜索
(2)深度优先搜索
二、面试常考的算法
1、实现深度优先搜索
题目:如下无向图,从节点A开始遍历,其深度优先搜索为:A B D E F C。
思路:深度优先搜索,创建visited数组,用于记录所有被访问过的顶点。
(1)从A出发,访问A。
(2)找出A的第一个没有被访问的邻接点,访问该点。以该顶点为新顶点,重复此步骤,直至刚访问过的顶点没有未被访问的邻接点为止。
(3)返回前一个访问过的仍有未被访问邻接点的顶点,继续访问该顶点的下一个未被访问邻接点。
(4)重复2,3步骤,直至所有顶点均被访问,搜索结束。
#include
using namespace std;
#include
#include
#include
#include
2、实现广度优先搜索
题目:如下无向图,从节点A开始遍历,其广度优先搜索为:A B D C E,从节点B开始遍历,其广度优先搜索为:B A C D E。
思路:广度优先搜索,利用队列来实现。把访问到的顶点入队,再访问该顶点的所有相邻的顶点,等访问完了该顶点的邻接点,再出队顶点和其相邻的顶点,每出队一个,就入队该顶点的未访问过的邻接顶点,重复上述步骤,直到队列为空。
#include
#include
#include
3、利用拓扑排序判断图是否有环路。
题目:如下有向图,判断是否存在环路。如果不为树,输出其拓扑排序。
思路:通过BFS实现拓扑排序。
(1)首先计算每个节点的入度,将所有入度为0的节点放入队列中
(2)开始执行BFS,我们取队首的节点u,放入结果中;移除u的所有出边,即将u的所有相邻节点的入度减少1,判断如果某个相邻的节点v的入度变为0,就将v放入队列中。
(3)当BFS结束后,如果答案中包含的节点数和图中的节点数相等,那么就得到了图G的拓扑排序,否则说明图中存在环,不存在拓扑排序。
// 利用拓扑排序判断有向图是否存在回路
#include
#include
4、计算图的边数
题目:给定如下无向图,输出该图的边数7。
思路:遍历图中的节点,若该节点的邻接节点没有被访问,则边数count+1。
#include
#include
#include
5、找到两个顶点之间的最短路径
题目:如下无向图,A到F的路径有A->B->C->E->F,A->B->C->F,A->D->E->F,输出最短路径A->D->E->F。
思路:广度优先搜索(BFS)+ 队列实现。
(1)准备queue和map,queue用于BFS,map>用于存储当前最短距离。
(2)BFS,将顶点node1入队,并向Map中添加键值对。
(3)当队列非空时,进行循环。现将队首元素x出队,当前路径等x的当前路径,然后遍历x的邻接节点,如果邻接点中的某个节点tmp不在map键值对中(相当于未访问过), 就向Map中加入键值对,并将tmp入队,如果tmp为node2,就返回Map中tmp对应的路径。
#include
#include
#include