引言
在计算机科学领域,数据结构和算法是程序员工具箱中的两大瑰宝。其中,图(Graph) 是一种极其重要的非线性数据结构,它以节点和边的概念描述实体间复杂的关系网络。本文将对图的数据结构进行详尽解析,探讨其基本概念、操作以及实际应用场景。
一、什么是图?
图 是由一组顶点(或称为节点)以及连接这些顶点的边构成的抽象数据类型。根据边的特性,图可以进一步分为无向图和有向图:
- 无向图 中每条边没有方向,表示两个顶点之间的关系是对称的。
- 有向图 中的边具有方向性,从一个顶点指向另一个顶点,表示单向依赖或流向关系。
此外,根据边是否有权重,又可将图划分为带权图和无权图。
二、图的基本操作
- 创建图:初始化图结构,包括创建空图、添加顶点和边等操作。
- 遍历图:主要有深度优先搜索(DFS)、广度优先搜索(BFS)两种方式,用于访问图中所有顶点或寻找特定路径。
- 查找路径:如Dijkstra算法求最短路径,Floyd-Warshall算法求任意两点间的最短路径,A*搜索算法在启发式指导下寻找最优路径等。
- 判断连通性:检查图中是否存在从一个顶点到另一个顶点的路径。
- 拓扑排序:对于有向无环图(DAG),按依赖关系进行排序。
三、图的应用场景
- 社交网络:用户之间的好友关系、关注关系可以用图来建模,便于进行好友推荐、社区发现等任务。
- 交通网络:地图上的道路系统、城市间航班或铁路线路可用图表示,方便计算最佳出行路线。
- 网页链接结构:互联网上的网页通过超链接形成巨大的有向图,搜索引擎正是利用此结构进行网页抓取和排名计算(PageRank算法)。
- 电路设计:电路中的各个元件及其连接关系可以通过图来描绘,辅助分析电路功能及故障排查。
- 生物信息学:基因调控网络、蛋白质相互作用网络等复杂生物学系统也可用图来刻画。
四、图算法的实际应用案例
- Google PageRank:使用有向有权图模型量化网页的重要性,并据此优化搜索结果排序。
- Facebook的朋友推荐系统:基于社交网络图构建算法,实现朋友推荐功能。
- GPS导航系统:采用图数据结构处理地理信息,实时规划出最优行驶路径。
五、图的代码实践
1.创建图(邻接矩阵)
public class Graph {
private ArrayList<String> vertexList; //存储定点的集合
private int[][] edges; //存储图对应的领接矩阵
private int numOfEdges; //边的数目
public static void main(String[] args) {
int n = 5;
String[] vertexs = {"A", "B", "C", "D", "E"};
Graph graph = new Graph(n);
for (String vertex : vertexs) {
graph.addVertex(vertex);
}
graph.addEdge(0, 1, 1);
graph.addEdge(0, 2, 1);
graph.addEdge(1, 2, 1);
graph.addEdge(1, 3, 1);
graph.addEdge(1, 4, 1);
graph.show();
}
public Graph(int n) {
edges = new int[n][n];
vertexList = new ArrayList<String>(n);
numOfEdges = 0;
}
// 添加定点
public void addVertex(String vertex) {
vertexList.add(vertex);
}
// 返回下标对应数据
public String getValueByIndex(int i) {
return vertexList.get(i);
}
// 返回下标对应数据
public String getValueByIndex(int i) {
return vertexList.get(i);
}
// 添加边
/**
* @param v1 顶点的下标
* @param v2 顶点的下标
* @param weight 权值
*/
public void addEdge(int v1, int v2, int weight) {
edges[v1][v2] = weight;
edges[v2][v1] = weight;
numOfEdges++;
}
// 得到边的数目
public int getNumOfEdges() {
return numOfEdges;
}
// 得到边的权值
public int getWeight(int v1, int v2) {
return edges[v1][v2];
}
// 展示图的邻接矩阵
public void show() {
for (int[] edge : edges) {
System.out.println(Arrays.toString(edge));
}
}
}
2.图的邻接矩阵结果
3.图的深度优先遍历
思路:
1.访问初始节点v,并标记节点v已访问
2.查找节点v的第一个邻接节点w
3.若w存在,则继续执行4,若其不存在,则回到1,将从v的下一个节点继续
4.若w未被访问,对w进行深度优先遍历递归(即把w当做另一个v,然后进行123)
5.查找节点v的w邻接节点的下一个邻接节点,在进行步骤3
代码
1,辅助方法
// 得到第一个邻接节点的下标w
/**
* @param index
* @return 如果存在返回对应下标,否则-1
*/
public int getFirstNeighbor(int index) {
for (int j = 0; j < vertexList.size(); j++) {
if (edges[index][j] > 0) {
return j;
}
}
return -1;
}
// 根据前一个邻接接节点的下标获取下一个邻接节点
public int getNextNeighbor(int v1, int v2) {
for (int j = v2 + 1; j < vertexList.size(); j++) {
if (edges[v1][j] > 0) {
return j;
}
}
return -1;
}
2.dfs算法
// 深度优先遍历算法
private void dfs(boolean[] isVisited, int i) {
// 首先访问该节点
System.out.print(getValueByIndex(i) + "->");
// 访问了给他设置访问
isVisited[i] = true;
// 查找i节点第一个邻接节点w
int w = getFirstNeighbor(i);
while (w != -1) {
if (!isVisited[w]) {
dfs(isVisited, w);
}
// 如果w已经被访问
w = getNextNeighbor(i, w);
}
}
// 对dfs进行一个重载遍历所有的节点
public void dfs() {
isVisited = new boolean[5];
for (int i = 0; i < vertexList.size(); i++) {
if (!isVisited[i]) {
dfs(isVisited, i);
}
}
}
4.图的广度优先
思路:
1.访问初始节点v,并标记节点v已访问
2.节点v入队列
3.当队列非空时,继续执行,否则算法结束
4.出队列,取得队列头结点u
5.查找节点u的第一个邻接节点w
6.若w不存在,则进行步骤3,否则循环执行下三个步骤
6.1若w未被访问,则访问节点w并标记已访问
6.2节点w入队列
6.3查找u的继w邻接节点后的下一个邻接节点w,再进行步骤6
代码
1.bfs算法
// 对一个节点进行广度优先遍历
public void bfs(boolean[] isVisited, int i) {
int u; //表示队列的头结点对应的下标
int w; //邻接节点
// 队列,记录节点访问的顺序
LinkedList queue = new LinkedList();
System.out.print(getValueByIndex(i) + "->");
isVisited[i] = true;
queue.addLast(i);
while (!queue.isEmpty()) {
u = (Integer)queue.removeFirst();
w = getFirstNeighbor(u);
while (w != -1) {
if (!isVisited[w]) {
System.out.print(getValueByIndex(w) + "->");
isVisited[w] = true;
queue.addLast(w);
}
w = getNextNeighbor(u, w);
}
}
}
// 遍历所有的节点广度优先
public void bfs() {
isVisited = new boolean[5];
for (int i = 0; i < vertexList.size(); i++) {
if (!isVisited[i]) {
bfs(isVisited, i);
}
}
}
5.dfs和bfs代码运行结果
六、总结
图作为复杂网络关系的有效模型,在现代计算机科学中扮演着至关重要的角色。理解并熟练掌握图相关的数据结构与算法,不仅能帮助我们解决众多实际问题,更能提升我们在复杂系统分析和设计方面的综合能力。无论是理论研究还是软件开发实践,图都是每一位计算机科学家和技术开发者必须掌握的核心知识点。
标签:return,int,public,算法,vertexList,数据结构,节点,isVisited From: https://blog.csdn.net/m0_62988332/article/details/136661982