Java 算法:带权图Weighted Graph
带权图,每条边相应都有一组值:
不同的权图可以有不同类型的值。
邻接矩阵:
0 0 1 2 3
0 0 0.12 0 0
1 0.12 0 0.34 0.52
2 0 0.34 0 0.22
3 0 0.52 0.28 0
邻接表:
0 {to:1,w:0.12}
1 {to:0,w:0.12}、 {to:2,w:0.34}、 {to:3,w:0.52}
2 {to:1,w:0.34}、 {to:3,w:0.28}
3 {to:1,w:0.52}、 {to:2,w:0.28}
对权图边与值封装成一个类:
// 边
public class Edge<Weight extends Number & Comparable> implements Comparable<Edge>{//有向边,从a指向bprivate int a, b; // 边的两个端点private Weight weight; // 边的权值public Edge(int a, int b, Weight weight){this.a = a;this.b = b;this.weight = weight;}public Edge(Edge<Weight> e) {this.a = e.a;this.b = e.b;this.weight = e.weight;}public int v(){ return a;} // 返回第一个顶点public int w(){ return b;} // 返回第二个顶点public Weight wt(){ return weight;} // 返回权值// 给定一个顶点, 返回另一个顶点public int other(int x){assert x == a || x == b;return x == a ? b : a;}// 输出边的信息public String toString(){return "" + a + "-" + b + ": " + weight;}// 边之间的比较public int compareTo(Edge that){if( weight.compareTo(that.wt()) < 0 ){return -1;}else if ( weight.compareTo(that.wt()) > 0 ){return +1;}else{return 0;}}
}
稠密图:邻接矩阵。
import java.util.Vector;// 稠密图 - 邻接矩阵
public class DenseWeightedGraph<Weight extends Number & Comparable>implements WeightedGraph{private int n; // 节点数private int m; // 边数private boolean directed; // 是否为有向图private Edge<Weight>[][] g; // 图的具体数据// 构造函数public DenseWeightedGraph( int n , boolean directed ){assert n >= 0;this.n = n;this.m = 0; // 初始化没有任何边this.directed = directed;// g初始化为n*n的布尔矩阵, 每一个g[i][j]均为null, 表示没有任和边// false为boolean型变量的默认值g = new Edge[n][n];for(int i = 0 ; i < n ; i ++){for(int j = 0 ; j < n ; j ++){g[i][j] = null;}}}public int V(){ return n;} // 返回节点个数public int E(){ return m;} // 返回边的个数// 向图中添加一个边public void addEdge(Edge e){assert e.v() >= 0 && e.v() < n ;assert e.w() >= 0 && e.w() < n ;if( hasEdge( e.v() , e.w() ) ){return;}g[e.v()][e.w()] = new Edge(e);if( e.v() != e.w() && !directed ){g[e.w()][e.v()] = new Edge(e.w(), e.v(), e.wt());}m ++;}// 验证图中是否有从v到w的边public boolean hasEdge( int v , int w ){assert v >= 0 && v < n ;assert w >= 0 && w < n ;return g[v][w] != null;}// 显示图的信息public void show(){for( int i = 0 ; i < n ; i ++ ){for( int j = 0 ; j < n ; j ++ ){if( g[i][j] != null ){System.out.print(g[i][j].wt()+"\t");}else{System.out.print("NULL\t");}}System.out.println();}}// 返回图中一个顶点的所有邻边// 由于java使用引用机制,返回一个Vector不会带来额外开销,public Iterable<Edge<Weight>> adj(int v) {assert v >= 0 && v < n;Vector<Edge<Weight>> adjV = new Vector<Edge<Weight>>();for(int i = 0 ; i < n ; i ++ ){if( g[v][i] != null ){adjV.add( g[v][i] );}}return adjV;}
}
稀疏图:邻接表。
import java.util.Vector;// 稀疏图 - 邻接表
public class SparseWeightedGraph<Weight extends Number & Comparable>implements WeightedGraph {private int n; // 节点数private int m; // 边数private boolean directed; // 是否为有向图private Vector<Edge<Weight>>[] g; // 图的具体数据// 构造函数public SparseWeightedGraph( int n , boolean directed ){assert n >= 0;this.n = n;this.m = 0; // 初始化没有任何边this.directed = directed;// g初始化为n个空的vector, 表示每一个g[i]都为空, 即没有任和边g = (Vector<Edge<Weight>>[])new Vector[n];for(int i = 0 ; i < n ; i ++){g[i] = new Vector<Edge<Weight>>();}}public int V(){ return n;} // 返回节点个数public int E(){ return m;} // 返回边的个数// 向图中添加一个边, 权值为weightpublic void addEdge(Edge e){assert e.v() >= 0 && e.v() < n ;assert e.w() >= 0 && e.w() < n ;// 注意, 由于在邻接表的情况, 查找是否有重边需要遍历整个链表// 我们的程序允许重边的出现g[e.v()].add(new Edge(e));if( e.v() != e.w() && !directed ){g[e.w()].add(new Edge(e.w(), e.v(), e.wt()));}m ++;}// 验证图中是否有从v到w的边public boolean hasEdge( int v , int w ){assert v >= 0 && v < n ;assert w >= 0 && w < n ;for( int i = 0 ; i < g[v].size() ; i ++ ){if( g[v].elementAt(i).other(v) == w )return true;}}return false;}// 显示图的信息public void show(){for( int i = 0 ; i < n ; i ++ ){System.out.print("vertex " + i + ":\t");for( int j = 0 ; j < g[i].size() ; j ++ ){Edge e = g[i].elementAt(j);System.out.print( "( to:" + e.other(i) + ",wt:" + e.wt() + ")\t");}System.out.println();}}// 返回图中一个顶点的所有邻边// 由于java使用引用机制,返回一个Vector不会带来额外开销,public Iterable<Edge<Weight>> adj(int v) {assert v >= 0 && v < n;return g[v];}
}
利用稠密图和稀疏图对文件图进行读取:
interface WeightedGraph<Weight extends Number & Comparable> {public int V();public int E();public void addEdge(Edge<Weight> e);boolean hasEdge( int v , int w );void show();public Iterable<Edge<Weight>> adj(int v);
}
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Scanner;
import java.util.Locale;
import java.util.InputMismatchException;
import java.util.NoSuchElementException;// 通过文件读取有全图的信息
public class ReadWeightedGraph{private Scanner scanner;// 由于文件格式的限制,我们的文件读取类只能读取权值为Double类型的图public ReadWeightedGraph(WeightedGraph<Double> graph, String filename){readFile(filename);try {int V = scanner.nextInt();if (V < 0){throw new IllegalArgumentException("number of vertices in a Graph must be nonnegative");}assert V == graph.V();int E = scanner.nextInt();if (E < 0){throw new IllegalArgumentException("number of edges in a Graph must be nonnegative");}for (int i = 0; i < E; i++) {int v = scanner.nextInt();int w = scanner.nextInt();Double weight = scanner.nextDouble();assert v >= 0 && v < V;assert w >= 0 && w < V;graph.addEdge(new Edge<Double>(v, w, weight));}}catch (InputMismatchException e) {String token = scanner.next();throw new InputMismatchException("attempts to read an 'int' value from input stream, but the next token is \"" + token + "\"");}catch (NoSuchElementException e) {throw new NoSuchElementException("attemps to read an 'int' value from input stream, but there are no more tokens available");}}private void readFile(String filename){assert filename != null;try {File file = new File(filename);if (file.exists()) {FileInputStream fis = new FileInputStream(file);scanner = new Scanner(new BufferedInputStream(fis), "UTF-8");scanner.useLocale(Locale.ENGLISH);}elsethrow new IllegalArgumentException(filename + " doesn't exist.");}catch (IOException ioe) {throw new IllegalArgumentException("Could not open " + filename, ioe);}}}
public class Main {// 测试通过文件读取图的信息public static void main(String[] args) {// 使用两种图的存储方式读取testG1.txt文件String filename = "testG1.txt";SparseWeightedGraph<Double> g1 = new SparseWeightedGraph<Double>(8, false);ReadWeightedGraph readGraph1 = new ReadWeightedGraph(g1, filename);System.out.println("test G1 in Sparse Weighted Graph:");g1.show();System.out.println();DenseWeightedGraph<Double> g2 = new DenseWeightedGraph<Double>(8, false);ReadWeightedGraph readGraph2 = new ReadWeightedGraph(g2 , filename );System.out.println("test G1 in Dense Graph:");g2.show();System.out.println();}
}
图:
8 16
4 5 .35
4 7 .37
5 7 .28
0 7 .16
1 5 .32
0 4 .38
2 3 .17
1 7 .19
0 2 .26
1 2 .36
1 3 .29
2 7 .34
6 2 .40
3 6 .52
6 0 .58
6 4 .93
Java 算法:带权图Weighted Graph相关推荐
- Java数据结构与算法:无向图,有向图,带权图,图的遍历,最小生成树
文章目录 无向图 有向图 带权图 图的遍历 广度优先遍历 深度优先遍历 最小生成树 无向图 前面了解到树是有单一根结点的非线性结构,图(graph)也是一种非线性结构,其中的结点可以与许多其他的结点相 ...
- 带权图的最短路径算法(Dijkstra)实现
一,介绍 本文实现带权图的最短路径算法.给定图中一个顶点,求解该顶点到图中所有其他顶点的最短路径 以及 最短路径的长度.在决定写这篇文章之前,在网上找了很多关于Dijkstra算法实现,但大部分是不带 ...
- 求的带权图最小生成树的Prim算法和Kruskal算法
求的带权图最小生成树的Prim算法和Kruskal算法 最小生成树的概念 最小生成树其实是最小权重生成树的简称. 一个连通图可能有多个生成树.当图中的边具有权值时,总会有一个生成树的边的权值之和小于或 ...
- 邻接表实现的有向带权图 及 图算法(C++)
邻接表实现的有向带权图 相关概念 声明和定义 实现 1. 构造函数 2. 析构函数 3. 深度优先遍历 4. 广度优先遍历 5. 获取顶点在邻接表中对应的下标 6. 添加顶点 7. 移除顶点 8. 添 ...
- python无向带权图
无向无权图见另一篇文章<python无向无权图结构>,这篇讲无向带权图,并且给出一个地铁线路例子. # -*- coding: UTF-8 -*- #!/usr/bin/python#-- ...
- c语言图的无向网存储,C语言——无向带权图邻接矩阵的建立
#include #include "Graph.h" #define MAX_INT 32767 /* #define vnum 20 #define MAX_INT = 327 ...
- 数据结构——图-有向带权图的邻接表
#include <stdio.h> #include <stdlib.h> #define VertexType char //顶点的数据类型(char) #define V ...
- 数据结构——图-有向带权图的邻接表基础
#include <stdio.h> #include <stdlib.h> #define VertexType char //顶点的数据类型(char) #define V ...
- 实现有向带权图抽象数据类型
题目 图是一种使用广泛的数据结构.本次实验要求设计有向带权图的抽象数据类型,实现图的构造.顶点的增删查,边的增删改.深度优先遍历与广度优先遍历.单源最短路径.多源最短路径.判断图中是否存在负环. 效果 ...
- 6.1图的定义、无向图、有向图、连通图、强连通图、带权图
1. 知识总览 2. 图的定义 3. 图逻辑结构的应用 4. 无向图.有向图 5. 简单图.多重图 6. 顶点的度.入度.出度 7. 连通图.强连通图 8. 研究图的局部–子图 9. 连通分量 10. ...
最新文章
- Python访问MySQL数据库
- 分布式存储的三个基本问题
- 网络安全netstat监听网络状态。
- 不一样的STAR法则
- 如何挽回一个快要“变心”的买家?
- 基于float的几种布局
- Linux下文件的多进程拷贝
- SQL 语句还原SQL Server数据库
- Java笔记-JPA保存数据时指定列不插入提交(CURRENT_TIMESTAMP)
- 从0到1构建支撑企业自动化运维体系
- Linux PPP实现源码分析-2
- 年度加密漏洞提前锁定:Java JDK 加密实现漏洞可用于伪造凭据
- 特斯拉电池检测_特斯拉风格的割草机,也是采用电池供电
- 前端面试常问的问题(必须掌握)
- Learn Git Branching 答案汇总
- op 消除 消除自激振荡
- Can't connect to MySQL server on 'localhost'(10038)的解决方案
- MySQL中Lob与JPA映射
- JAVA与PHP之间进行aes加密解密
- TMF和Frameworx