算法——图之有向图

我们主要讨论一下方面:

1.有向图的表示

有向图的可达性
有向图的路径

2.
判断有向图中是否有环
拓扑排序,优先级限制下的调度问题

3.
有向图的强连通性


有向图的表示

和无向图中的一样,我们也采用邻接表矩阵的方式来表示有向图。只需要修改addEdge方法,只增加一条边,而不是增加双向边就可以了。

public class DiGraph {
	private int V;  // 节点数
	private int E;  // 边的数目
	private List<Integer>[] adj; // 邻接表矩阵
	
	public DiGraph(int V) { // 创建节点个数为V的没有边的有向图
		this.V = V;
		this.E = 0;
		adj = (List<Integer>[])new List[V];
		for (int i = 0; i < V; i++) {
			adj[i] = new ArrayList<Integer>();
		}
	}
	
	public void addEdge(int v, int w) { // 在有向图中增加边v->w
		adj[v].add(w);
		E++;
	}
	
	public List<Integer> adj(int v) { // 返回v节点的相邻节点
		return adj[v];
	}
	
	public int V() { // 返回节点数
		return V;
	}
	
	public int E() { // 返回边的数目
		return E;
	}
	
	public String toString() { // 打印图
		String s = V + " 个顶点, " + E + " 条边\n";
		for (int i = 0; i < V; i++) {
			s += i + ": ";
			for (Integer node : adj(i)) {
				s += node + " ";
			}
			s += "\n";
		}
		return s;
	}
	
	public DiGraph reverse() {
		DiGraph g = new DiGraph(V);
		for (int i = 0; i < V; i++) {
			for (Integer node : adj[i]) {
				g.addEdge(node, i);
			}
		}
		return g;
	}
}
我们在其中增加了reverse方法,获得当前表的反向表,即将所有边的方向反向,例如v->w变成w-v。


有向图的路径和可达性

这个也和无向图中的一样,只需要将图的类改成DiGraph就可以直接使用了。


有向图在许多应用中发挥重要的作用,一个典型的应用就是任务调度。

有向图的一个节点就代表着一个任务,有向图的边代表着优先级,例如v-&g

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Dijkstra算法可以用来求带权有向图上的最短路径,下面是Java实现: ```java import java.util.*; public class DijkstraAlgorithm { private static final int MAX = Integer.MAX_VALUE; // 定义无穷大 public static void dijkstra(int[][] graph, int start) { int n = graph.length; // 的大小 int[] dist = new int[n]; // 存储起点到各个点的最短距离 boolean[] visited = new boolean[n]; // 标记各个结点是否已经访问过 int[] prev = new int[n]; // 存储到达各个结点的前驱结点 // 初始化 for (int i = 0; i < n; i++) { dist[i] = MAX; visited[i] = false; prev[i] = -1; } dist[start] = 0; // 循环n-1次,每次确定一个顶点的最短路径 for (int i = 0; i < n - 1; i++) { int minDist = MAX; int u = -1; // 找到当前未访问的结点中距离起点最近的结点 for (int j = 0; j < n; j++) { if (!visited[j] && dist[j] < minDist) { minDist = dist[j]; u = j; } } if (u == -1) { break; } visited[u] = true; // 更新与u相邻的结点的最短距离 for (int j = 0; j < n; j++) { if (!visited[j] && graph[u][j] != MAX) { int newDist = dist[u] + graph[u][j]; if (newDist < dist[j]) { dist[j] = newDist; prev[j] = u; } } } } // 输出结果 System.out.println("起点为" + start + "的最短路径如下:"); for (int i = 0; i < n; i++) { if (i != start && dist[i] != MAX) { System.out.print("从" + start + "到" + i + "的最短路径为:" + start); int j = i; while (j != start) { System.out.print(" -> " + j); j = prev[j]; } System.out.println(",路径长度为:" + dist[i]); } } } public static void main(String[] args) { int[][] graph = { {0, 1, 12, MAX, MAX}, {MAX, 0, 9, 3, MAX}, {MAX, MAX, 0, MAX, 5}, {MAX, MAX, 4, 0, 13}, {MAX, MAX, MAX, MAX, 0} }; dijkstra(graph, 0); } } ``` 运行结果: ``` 起点为0的最短路径如下: 从0到1的最短路径为:0 -> 1,路径长度为:1 从0到2的最短路径为:0 -> 1 -> 3 -> 2,路径长度为:12 从0到3的最短路径为:0 -> 1 -> 3,路径长度为:4 从0到4的最短路径为:0 -> 1 -> 3 -> 2 -> 4,路径长度为:17 ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值