有权图

概念

  • 边上有值;

边 - Edge

package _08._01;

// 边
public class Edge implements Comparable{

    private 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 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;
    }
}

有权图接口 - WeightedGraph

package _08._01;

interface WeightedGraph {
    public int V();
    public int E();
    public void addEdge(Edge e);
    boolean hasEdge(int v, int w);
    void show();
    public Iterable> adj(int v);
}

邻接矩阵实现 - DenseWeightedGraph

package _08._01;

import java.util.Vector;

// 稠密图 - 邻接矩阵
public class DenseWeightedGraph
        implements WeightedGraph{

    private int n;  // 节点数
    private int m;  // 边数
    private boolean directed;   // 是否为有向图
    private Edge[][] 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> adj(int v) {
        assert v >= 0 && v < n;
        Vector> adjV = new Vector>();
        for(int i = 0 ; i < n ; i ++ )
            if( g[v][i] != null )
                adjV.add( g[v][i] );
        return adjV;
    }
}

邻接表实现 - SparseWeightedGraph

package _08._01;

import java.util.Vector;

// 稀疏图 - 邻接表
public class SparseWeightedGraph
        implements WeightedGraph {

    private int n;  // 节点数
    private int m;  // 边数
    private boolean directed;   // 是否为有向图
    private Vector>[] 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>[])new Vector[n];
        for(int i = 0 ; i < n ; i ++)
            g[i] = new Vector>();
    }

    public int V(){ return n;} // 返回节点个数
    public int E(){ return m;} // 返回边的个数

    // 向图中添加一个边, 权值为weight
    public 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> adj(int v) {
        assert v >= 0 && v < n;
        return g[v];
    }
}

从文件中存储的数据生成图的工具类

package _08._01;

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 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(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);
            }
            else
                throw new IllegalArgumentException(filename + " doesn't exist.");
        }
        catch (IOException ioe) {
            throw new IllegalArgumentException("Could not open " + filename, ioe);
        }
    }

}

测试

package _08._01;

public class Main {

    // 测试通过文件读取图的信息
    public static void main(String[] args) {

        // 使用两种图的存储方式读取testG1.txt文件
        String filename = "testG1_w.txt";
        SparseWeightedGraph g1 = new SparseWeightedGraph(8, false);
        ReadWeightedGraph readGraph1 = new ReadWeightedGraph(g1, filename);
        System.out.println("test G1 in Sparse Weighted Graph:");
        g1.show();

        System.out.println();

        DenseWeightedGraph g2 = new DenseWeightedGraph(8, false);
        ReadWeightedGraph readGraph2 = new ReadWeightedGraph(g2 , filename );
        System.out.println("test G1 in Dense Graph:");
        g2.show();

        System.out.println();
    }
}
输出:
test G1 in Sparse Weighted Graph:
vertex 0:   ( to:7,wt:0.16) ( to:4,wt:0.38) ( to:2,wt:0.26) ( to:6,wt:0.58) 
vertex 1:   ( to:5,wt:0.32) ( to:7,wt:0.19) ( to:2,wt:0.36) ( to:3,wt:0.29) 
vertex 2:   ( to:3,wt:0.17) ( to:0,wt:0.26) ( to:1,wt:0.36) ( to:7,wt:0.34) ( to:6,wt:0.4)  
vertex 3:   ( to:2,wt:0.17) ( to:1,wt:0.29) ( to:6,wt:0.52) 
vertex 4:   ( to:5,wt:0.35) ( to:7,wt:0.37) ( to:0,wt:0.38) ( to:6,wt:0.93) 
vertex 5:   ( to:4,wt:0.35) ( to:7,wt:0.28) ( to:1,wt:0.32) 
vertex 6:   ( to:2,wt:0.4)  ( to:3,wt:0.52) ( to:0,wt:0.58) ( to:4,wt:0.93) 
vertex 7:   ( to:4,wt:0.37) ( to:5,wt:0.28) ( to:0,wt:0.16) ( to:1,wt:0.19) ( to:2,wt:0.34) 

test G1 in Dense Graph:
NULL    NULL    0.26    NULL    0.38    NULL    0.58    0.16    
NULL    NULL    0.36    0.29    NULL    0.32    NULL    0.19    
0.26    0.36    NULL    0.17    NULL    NULL    0.4 0.34    
NULL    0.29    0.17    NULL    NULL    NULL    0.52    NULL    
0.38    NULL    NULL    NULL    NULL    0.35    0.93    0.37    
NULL    0.32    NULL    NULL    0.35    NULL    NULL    0.28    
0.58    NULL    0.4 0.52    0.93    NULL    NULL    NULL    
0.16    0.19    0.34    NULL    0.37    0.28    NULL    NULL

你可能感兴趣的:(有权图)