1.加权无向图

加权无向图是一种为每条边关联一个权重值或是成本的图模型。这种图能够自然地表示许多应用。在一副航空图 中,边表示航线,权值则可以表示距离或是费用。在一副电路图中,边表示导线,权值则可能表示导线的长度即成 本,或是信号通过这条先所需的时间。此时我们很容易就能想到,最小成本的问题,例如,从西安飞纽约,怎样飞 才能使时间成本最低或者是金钱成本最低?

边的实现:

  1. package 图;
  2. public class Edge implements Comparable<Edge> {
  3. private final int v;//顶点一
  4. private final int w;//顶点二
  5. private final double weight;//当前边的权重
  6. //通过顶点v和w,以及权重weight值构造一个边对象
  7. public Edge(int v, int w, double weight) {
  8. this.v = v;
  9. this.w = w;
  10. this.weight = weight;
  11. }
  12. //获取边的权重值
  13. public double weight() {
  14. return weight;
  15. }
  16. //获取边上的一个点
  17. public int either() {
  18. return v;
  19. }
  20. //获取边上除了顶点vertex外的另外一个顶点
  21. public int other(int vertex) {
  22. if (vertex == v) {
  23. //如果传入的顶点vertext是v,则返回另外一个顶点w
  24. return w;
  25. } else {
  26. //如果传入的顶点vertext不是v,则返回v即可
  27. return v;
  28. }
  29. }
  30. @Override
  31. public int compareTo(Edge that) {
  32. int cmp;
  33. if (this.weight() > that.weight()) {
  34. //如果当前边的权重大于参数边that的权重,返回1
  35. cmp = 1;
  36. } else if (this.weight() < that.weight()) {
  37. //如果当前边的权重小于参数边that的权重,返回-1
  38. cmp = -1;
  39. } else {
  40. //如果当前边的权重等于参数边that的权重,返回0
  41. cmp = 0;
  42. }
  43. return cmp;
  44. }
  45. }

加权无向图的实现:

  1. package 图;
  2. import 线性表.Queue;
  3. public class EdgeWeightedGraph {
  4. //顶点总数
  5. private final int V;
  6. //边的总数
  7. private int E;
  8. //邻接表
  9. private Queue<Edge>[] adj;
  10. //创建一个含有V个顶点的空加权无向图
  11. public EdgeWeightedGraph(int V) {
  12. //初始化顶点数量
  13. this.V = V;
  14. //初始化边的数量
  15. this.E = 0;
  16. //初始化邻接表
  17. this.adj = new Queue[V];
  18. //初始化邻接表中的空队列
  19. for (int i = 0; i < adj.length; i++) {
  20. adj[i] = new Queue<Edge>();
  21. }
  22. }
  23. //获取图中顶点的数量
  24. public int V() {
  25. return V;
  26. }
  27. //获取图中边的数量
  28. public int E() {
  29. return E;
  30. }//向加权无向图中添加一条边e
  31. public void addEdge(Edge e) {
  32. //获取边中的一个顶点v
  33. int v = e.either();
  34. //获取边中的另一个顶点w
  35. int w = e.other(v);
  36. //因为是无向图,所以边e需要同时出现在两个顶点的邻接表中
  37. adj[v].enqueue(e);
  38. adj[w].enqueue(e);
  39. //边的数量+1
  40. E++;
  41. }
  42. //获取和顶点v关联的所有边
  43. public Queue<Edge> adj(int v) {
  44. return adj[v];
  45. }
  46. //获取加权无向图的所有边
  47. public Queue<Edge> edges() {
  48. //创建一个队列,存储所有的边
  49. Queue<Edge> allEdge = new Queue<>();
  50. //遍历顶点,拿到每个顶点的邻接表
  51. for (int v = 0; v < this.V; v++) {
  52. //遍历邻接表,拿到邻接表中的每条边
  53. for (Edge e : adj(v)) {
  54. /*
  55. 因为无向图中,每条边对象Edge都会在两个顶点的邻接表中各出现一次,为了不重复获取,暂定
  56. 一条规则:
  57. 除了当前顶点v,再获取边e中的另外一个顶点w,如果v<w则添加,这样可以保证同一条边
  58. 只会被统计一次
  59. */
  60. if (e.other(v) < v) {
  61. allEdge.enqueue(e);
  62. }
  63. }
  64. }
  65. return allEdge;
  66. }
  67. }

2.加权有向图

边的实现:

  1. package 图;
  2. public class DirectedEdge {
  3. private final int v;//起点
  4. private final int w;//终点
  5. private final double weight;//当前边的权重
  6. //通过顶点v和w,以及权重weight值构造一个边对象
  7. public DirectedEdge(int v, int w, double weight) {
  8. this.v = v;
  9. this.w = w;
  10. this.weight = weight;
  11. }
  12. //获取边的权重值
  13. public double weight() {
  14. return weight;
  15. }
  16. //获取有向边的起点
  17. public int from() {
  18. return v;
  19. }
  20. //获取有向边的终点
  21. public int to() {
  22. return w;
  23. }
  24. }

加权有向图的实现:

  1. package 图;
  2. import 线性表.Queue;
  3. public class EdgeWeightedDigraph {
  4. //顶点总数
  5. private final int V;
  6. //边的总数
  7. private int E;
  8. //邻接表
  9. private Queue<DirectedEdge>[] adj;
  10. //创建一个含有V个顶点的空加权有向图
  11. public EdgeWeightedDigraph(int V) {
  12. //初始化顶点数量
  13. this.V = V;
  14. //初始化边的数量
  15. this.E = 0;
  16. //初始化邻接表
  17. this.adj = new Queue[V];
  18. //初始化邻接表中的空队列
  19. for (int i = 0; i < adj.length; i++) {
  20. adj[i] = new Queue<DirectedEdge>();
  21. }
  22. }
  23. //获取图中顶点的数量
  24. public int V() {
  25. return V;
  26. }
  27. //获取图中边的数量
  28. public int E() {
  29. return E;
  30. }
  31. //向加权有向图中添加一条边e
  32. public void addEdge(DirectedEdge e) {
  33. //获取有向边的起点
  34. int v = e.from();
  35. //因为是有向图,所以边e只需要出现在起点v的邻接表中
  36. adj[v].enqueue(e);
  37. //边的数量+1
  38. E++;
  39. }
  40. //获取由顶点v指出的所有的边
  41. public Queue<DirectedEdge> adj(int v) {
  42. return adj[v];
  43. }
  44. //获取加权有向图的所有边
  45. public Queue<DirectedEdge> edges() {
  46. //创建一个队列,存储所有的边
  47. Queue<DirectedEdge> allEdge = new Queue<>();
  48. //遍历顶点,拿到每个顶点的邻接表
  49. for (int v = 0; v < this.V; v++) {
  50. //遍历邻接表,拿到邻接表中的每条边存储到队列中
  51. for (DirectedEdge e : adj(v)) {
  52. allEdge.enqueue(e);
  53. }
  54. }
  55. return allEdge;
  56. }
  57. }