第三章 算法与数据结构 - 3.4 图算法
1.1 广度优先遍历 (BFS)
类似树的层次遍历,首先访问起始顶点v,然后选取与v邻接的全部顶点w1,w2,…wn,进行访问。再依次访问与w1,w2,…wn邻接的全部顶点。依次类推,直到所有顶点都被访问过为止。从顶点一层层向外拓展和遍历,实现是需要用到队列。
1.2 深度优先遍历(DFS)
首先访问出发节点v,将其标记为已访问过;然后选取与v邻接的未被访问的任意一个顶点w,并访问它;再选取与w邻接的未被访问的任意一个顶点并访问,依次重复进行。当一个顶点的所有邻接顶点都被访问过,则依次退回到最近被被访问过的顶点,如果该顶点还有其他邻接顶点未被访问,则从这些未被访问的顶点中取一个重复上述访问过程。
二. 最小生成树
Prim 普里姆算法
思路: 该算法采用贪心思想,在图中任意选择一结点构建一颗生成树然后从所有与该生成树相邻的结点中取出最近的结点和边加入到生成树中.直到所有的结点都加入到该生成树中.
算法复杂度 ElogV
采用最小优先队列存放剩余的结点,每次从该最小队列中选出与生成树之间最小的结点加入生成树中,同时更新最小队列.
克鲁斯卡尔
克鲁斯卡尔算法每次从剩余的边中选择一个最小的边,如果当前边和已选取的边构成回路,则放弃该并选择下一个最小边。如果不构成回路则将该边以及连接的两个结点加入的生成树中.直到完成整棵生成树的构建.
时间复杂度, ElogE
三. 距离
迪杰斯特拉 Dijkstra
思路: 它应用了贪心算法模式,算法解决的是有向图中单个源点到其他顶点的最短路径问题.引进两个集合S和T。S的作用是记录已求出最短路径的顶点(以及相应的最短路径长度),而T则是记录还未求出最短路径的顶点(以及该顶点到起点s的距离)。
初始时,S中只有起点v0;T中是除v0之外的顶点,并且T中顶点的路径是”起点s到该顶点的路径”。从T中选择一个到v0最短的顶点vi并加入到S中.如果T集合中的结点以vi作为中转站到达s的距离比原来的小则更新对应的值.依次迭代,直到将T中的所有结点加入S中.
算法复杂度 ElogV
弗洛伊德 Floyed
是采用动态规划的思想计算任意两个结点之间的最短路径.
1) 初始化距离矩阵,对于所有两点之间的距离是边的权,如果两点之间没有边相连,则权为无穷大。
2,对于每一对顶点 u 和 v,看看其他结点中否存在一个顶点 w 使得从 u 到 w 再到 v 比已知的路径更短。如果是更新它。
应用:
在网络中
时间复杂度O(V^3)。
public class Floyed {
private final int INF = Integer.MAX_VALUE;
/**
* 弗洛伊德算法
* @param matrix
*/
public void Floyd(int[][] matrix) {
int[][] path = new int[matrix.length][matrix[0].length];
int[][] dist = new int[matrix.length][matrix[0].length];
int size = matrix.length;
//初始化
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
path[i][j] = -1;
dist[i][j] = matrix[i][j];
}
}
for (int k = 0; k < size; k++) {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
if (dist[i][k] != INF && dist[k][j] != INF && dist[i][k] + dist[k][j] < dist[i][j]) {
dist[i][j] = dist[i][k] + dist[k][j];
path[i][j] = k;
}
}
}
}
}
}