思维导图

图的定义
无论多么复杂的图都是由顶点和边构成的。
在无向图中,若存在一条边(i,j),则称顶点i和顶点j为该边的两个端点,并称他们互为临接点
在有向图中,若存在一条有向边<i,j>,则顶点i和顶点j分别称为起始端点和终止端点
在无向图中,一个顶点所关联的边的数目称为该顶点的度
在有向图中,顶点的度又分为入度和出度
在无向图中,任意两点都存在一条边,有向图中任意两个顶点都存在方向相反的边,则该图成为完全图
顶点i和顶点有路径,则i和j是连通的
图中任意一对的顶点之间都有路径,那么就是强连通图。
图的存储
临界矩阵
用一个一维数组存放顶点集合,一个二维数组存放边的信息(称为邻接矩阵),边是可以带权值的
#define MAXVEXNUM 100 //点,边
typedef char VexType; //点的类型
typedef int ArcCell; //边的类型
typedef struct
{
VexType vexs[MAXVEXNUM]; //点的集合
ArcCell arcs[MAXVEXNUM][MAXVEXNUM]; //边的集合
int vexNum, arcNum; //点和边的个数
} MyGraph;
对无向图而言,邻接矩阵一定是对称的,而且主对角线一般为零。
邻接表
图的邻接表存储方法一种顺序分配和链式分配相结合的存储结构。如这个表头结点所对应的顶点存在相邻顶点,则把相邻顶点依次存放于表头结点所指向的单向链表中。
#define MAXVEXNUM 100 //点
typedef char VertexType; //顶点的类型
typedef int EdgeType; //边的类型
typedef struct EdgeNode //边表结点
{
VertexType data; //点
EdgeType weight; // 权值
EdgeNode *next; //下一个点
} EdgeNode;
typedef struct VexNode //顶点表结点
{
VertexType data; //顶点
EdgeNode *firstEdge; //指向第一个临界点
}VexList[MAXVEXNUM];
图的遍历
dfs
在搜索其余的路径结果之前必须先完整地搜索单独的一条路径。采用栈
bfs
每次拓展当前结点的所有出度。它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。采用队列。
图的应用
最小生成树
Prim
每次从已经生成的树中,向其他点拓展一条最短边。
for (i = 1; i < Vexnum; i++)
{
min = MAX;
//求出与集合U权值最小的点 权值为0的代表在集合U中
for (int j = 0; j < Vexnum; j++)
{
if (cost[j] != 0 && cost[j] < min)
{
min = cost[j];
k = j;
}
}
mincost += min;//累加
//更新最小边
for (int j = 0; j < Vexnum; j++)
{
if (cost[j] != 0 && a[k][j] < cost[j])
{
cost[j] = k;
cost[j] = a[k][j];
}
}
}
Kruskal
按边的权值排序,用并查集判断是否在同一个集合。
struct Edge
{
int x, y;
int data;
} a[EMAX];
bool cmp(Edge x, Edge y) //排序
{
return x.data < y.data;
}
int Find(int x)//查询所在集合
{
if (x != Fa[x])
Fa[x] = Find(Fa[x]);
return Fa[x];
}
viod Uni(int x, int y)//合集
{
Fa[Find(x)] = Find(y);
}
void slove()
{
sort(a, a + En, cmp);
int d = 0;
for (int i = 0; i < En; ++i)
{
if (Find(a[i].x) != Find(a[i].y))//判断是否同一集合
{
d++;
Uni(Find(a[i].x), Find(a[i].y)) //合集
}
if(d==n-1)
break;
}
}
最短路径
Dijkstra
Dijkstra算法主要特点是从起始点开始,采用贪心算法的策略,每次遍历到始点距离最近且未访问过的顶点的邻接节点,直到扩展到终点为止。
for (i = 1; i <= n; i++)
{
Vmin = MAX;//初始化最小值
k = 0;
for (j = 1; j <= n; j++)//找到未访问节点中d[j]值最小的那个节点,
if (!p[j] && d[j] < Vmin)
{
Vmin = d[j];
k = j;
}
p[k] = 1; //标记第k个节点已经访问过了
for (j = 1; j <= n; j++)
if (a[k][j] != 0 && !p[j] && d[j] > d[k] + a[k][j])
d[j] = d[k] + a[k][j];
}
Floyd
Floyd算法又称为插点法,是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,与Dijkstra算法类似。
for (k = 0; k < Vernum; ++k)
for (i = 0; i < Vernum; ++i)
for (j = 0; j < Vernum; ++j)
if (a[i][k] + a[k][j] < a[i][j]) //i到k的距离+k到j的距离 比较 i到j的距离,
a[i][j] = a[i][k] + a[k][j]; //更新
本文介绍了图的基本概念,包括无向图和有向图的定义,顶点的度以及完全图的概念。讨论了图的存储方式,如邻接矩阵和邻接表,并详细阐述了深度优先搜索(DFS)和广度优先搜索(BFS)两种图的遍历算法。此外,还探讨了图的应用,包括Prim和Kruskal算法用于构造最小生成树,以及Dijkstra和Floyd算法解决最短路径问题。

被折叠的 条评论
为什么被折叠?



