加权无向图

加权无向图

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

在下图中,从顶点0到顶点4有三条路径,分别为0-2-3-4,0-2-4,0-5-3-4,那我们如果要通过那条路径到达4顶点最好呢?此时就要考虑,那条路径的成本最低。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bLRnBVF0-1630077471320)(images/image69.png)]

1. 加权无向图边的表示

加权无向图中的边我们就不能简单的使用v-w两个顶点表示了,而必须要给边关联一个权重值,因此我们可以使用对象来描述一条边。

API设计:

类名Edge implements Comparable
构造方法Edge(int v,int w,double weight):通过顶点v和w,以及权重weight值构造一个边对象
成员方法1.public double weight():获取边的权重值
2.public int either():获取边上的一个点
3.public int other(int vertex)):获取边上除了顶点vertex外的另外一个顶点
4.public int compareTo(Edge that):比较当前边和参数that边的权重,如果当前边权重大,返回1,如果一样大,返回0,如果当前权重小,返回-1
成员变量1.private fifinal int v:顶点一
2.private fifinal int w:顶点二
3.private fifinal double weight:当前边的权重

代码:

/**
 * 加权无向图的边
 */
public class Edge implements Comparable<Edge> {
    // 顶点一
    private final int v;
    // 顶点二
    private final int w;
    // 当前边的权重
    private final double weight;

    // 通过顶点v和w,以及权重weight值构造一个边对象
    public Edge(int v, int w, double weight) {
        this.v = v;
        this.w = w;
        this.weight = weight;
    }

    // 获取边的权重值
    public double weight() {
        return weight;
    }

    // 获取边上的一个点
    public int either() {
        return v;
    }

    // 获取边上除了顶点vertex外的另外一个顶点
    public int other(int vertex) {
        if (vertex == v) {
            // 如果传入的vertex是v,则返回另一个顶点w
            return w;
        } else {
            // 如果传入的vertex是w,则返回另一个顶点v
            return v;
        }
    }

    @Override
    public int compareTo(Edge o) {
        int cmp = 0;
        if (this.weight() > o.weight()) {
            // 当前边权重>o边的权重,返回1
            cmp = 1;
        }
        if (this.weight() == o.weight()) {
            // 当前边权重=o边的权重,返回0
            cmp = 0;
        }
        if (this.weight() < o.weight()) {
            // 当前边权重<o边的权重,返回0
            cmp = -1;
        }
        return cmp;
    }
}

2.加权无向图的实现

在无向图的基础上,我们只需要把边的表示切换成Edge对象即可。

API设计:

类名EdgeWeightedGraph
构造方法EdgeWeightedGraph(int V):创建一个含有V个顶点的空加权无向图
成员方法1.public int V():获取图中顶点的数量
2.public int E():获取图中边的数量
3.public void addEdge(Edge e):向加权无向图中添加一条边e
4.public Queue adj(int v):获取和顶点v关联的所有边
5.public Queue edges():获取加权无向图的所有边
成员变量1.private fifinal int V: 记录顶点数量
2.private int E: 记录边数量
3.private Queue[] adj: 邻接表

代码:

/**
 * 加权无向图
 */
public class EdgeWeightedGraph {
    // 记录顶点数量
    private final int V;
    // 记录边数量
    private int E;
    // 邻接表
    private Queue<Edge>[] adj;

    // 创建一个含有V个顶点的空加权无向图
    public EdgeWeightedGraph(int v) {
        // 初始化顶点数量
        this.V = v;
        // 初始化边数量
        this.E = 0;
        // 初始化邻接表
        this.adj = new Queue[V];
        // 初始化邻接表中的空队列
        for (int i = 0; i < v; i++) {
            adj[i] = new Queue<Edge>();
        }
    }

    // 获取图中顶点的数量
    public int V() {
        return V;
    }

    // 获取图中边的数量
    public int E() {
        return E;
    }

    // 向加权无向图中添加一条边e
    public void addEdge(Edge e) {
        // 获取边的一个顶点
        int v = e.either();
        // 获取边的另一个顶点
        int w = e.other(v);
        // 无向图,两个顶点都要记录边
        adj[v].enqueue(e);
        adj[w].enqueue(e);
        // 边的数量+1
        E++;
    }

    // 获取和顶点v关联的所有边
    public Queue<Edge> adj(int v) {
        return adj[v];
    }

    // 获取加权无向图的所有边
    public Queue<Edge> edges() {
        // 创建一个队列,存储所有的边
        Queue<Edge> allEdge = new Queue<>();
        // 遍历每个顶点,拿到其对应的邻接表
        for (int v = 0; v < V; v++) {
            // 遍历邻接表中的边,添加到队列中
            for (Edge e : adj[v]) {
                /*
                    无向图的边在邻接表中会重复存储,v的邻接表存储边e,w的邻接表也存储边e
                    但是每条边相连的两个顶点是v<w的,
                    所以只要判断边相连的两个顶点是v<w,再将边入队列,就会去掉重复的边
                 */
                if (v < e.other(v)) {
                    allEdge.enqueue(e);
                }
            }
        }
        return allEdge;
    }
}
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

农村小白i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值