Java數(shù)據(jù)結(jié)構(gòu)之加權(quán)無向圖的設(shè)計(jì)實(shí)現(xiàn)
前言
加權(quán)無向圖是一種為每條邊關(guān)聯(lián)一個(gè)權(quán)重值或是成本的圖模型。這種圖能夠自然地表示許多應(yīng)用。在一副航空?qǐng)D中,邊表示航線,權(quán)值則可以表示距離或是費(fèi)用。在一副電路圖中,邊表示導(dǎo)線,權(quán)值則可能表示導(dǎo)線的長(zhǎng)度即成本,或是信號(hào)通過這條先所需的時(shí)間。此時(shí)我們很容易就能想到,最小成本的問題,例如,從西安飛紐約,怎樣飛才能使時(shí)間成本最低或者是金錢成本最低?
在下圖中,從頂點(diǎn)0到頂點(diǎn)4有三條路徑,分別為0-2-3-4,0-2-4,0-5-3-4,那我們?nèi)绻ㄟ^那條路徑到達(dá)4頂點(diǎn)最好呢?此時(shí)就要考慮,那條路徑的成本最低。

邊的表示
加權(quán)無向圖中的邊我們就不能簡(jiǎn)單的使用v-w兩個(gè)頂點(diǎn)表示了,而必須要給邊關(guān)聯(lián)一個(gè)權(quán)重值,因此我們可以使用對(duì)象來描述一條邊。
API設(shè)計(jì)
| 類名 | Edge implements Comparable |
|---|---|
| 成員變量 | 1.private final int v:頂點(diǎn)一2.private final int w:頂點(diǎn)二3.private final double weight:當(dāng)前邊的權(quán)重 |
| 構(gòu)造方法 | Edge(int v,int w,double weight):通過頂點(diǎn)v和w,以及權(quán)重weight值構(gòu)造一個(gè)邊對(duì)象 |
| 成員方法 | 1.public double weight():獲取邊的權(quán)重值2.public int either():獲取邊上的一個(gè)點(diǎn)3.public int other(int vertex)):獲取邊上除了頂點(diǎn)vertex外的另外一個(gè)頂點(diǎn)4.public int compareTo(Edge that):比較當(dāng)前邊和參數(shù)that邊的權(quán)重,如果當(dāng)前邊權(quán)重大,返回1,如果一樣大,返回0,如果當(dāng)前權(quán)重小,返回-1 |
代碼實(shí)現(xiàn)
/**
* 邊
*
* @author alvin
* @date 2022/11/3
* @since 1.0
**/
public class Edge implements Comparable<Edge> {
//頂點(diǎn)一
private final int v;
//頂點(diǎn)二
private final int w;
//當(dāng)前邊的權(quán)重
private final double weight;
//通過頂點(diǎn)v和w,以及權(quán)重weight值構(gòu)造一個(gè)邊對(duì)象
public Edge(int v, int w, double weight) {
this.v = v;
this.w = w;
this.weight = weight;
}
//獲取邊的權(quán)重值
public double weight() {
return weight;
}
//獲取邊上的一個(gè)點(diǎn)
public int either() {
return v;
}
//獲取邊上除了頂點(diǎn)vertex外的另外一個(gè)頂點(diǎn)
public int other(int vertex) {
if (vertex == v) {
return w;
} else {
return v;
}
}
@Override
public int compareTo(Edge that) {
//使用一個(gè)遍歷記錄比較的結(jié)果
int cmp;
if (this.weight() > that.weight()) {
//如果當(dāng)前邊的權(quán)重值大,則讓cmp=1;
cmp = 1;
} else if (this.weight() < that.weight()) {
//如果當(dāng)前邊的權(quán)重值小,則讓cmp=-1;
cmp = -1;
} else {
//如果當(dāng)前邊的權(quán)重值和that邊的權(quán)重值一樣大,則讓cmp=0
cmp = 0;
}
return cmp;
}
}圖的實(shí)現(xiàn)
之前我們已經(jīng)完成了無向圖,在無向圖的基礎(chǔ)上,我們只需要把邊的表示切換成Edge對(duì)象即可。
API設(shè)計(jì)
| 類名 | EdgeWeightedGraph |
|---|---|
| 成員變量 | 1.private final int V: 記錄頂點(diǎn)數(shù)量2.private int E: 記錄邊數(shù)量3.private Queue[] adj: 鄰接表 |
| 構(gòu)造方法 | EdgeWeightedGraph(int V):創(chuàng)建一個(gè)含有V個(gè)頂點(diǎn)的空加權(quán)無向圖 |
| 成員方法 | 1.public int V():獲取圖中頂點(diǎn)的數(shù)量2.public int E():獲取圖中邊的數(shù)量3.public void addEdge(Edge e):向加權(quán)無向圖中添加一條邊e4.public Queue adj(int v):獲取和頂點(diǎn)v關(guān)聯(lián)的所有邊5.public Queue edges():獲取加權(quán)無向圖的所有邊 |
代碼實(shí)現(xiàn)
/**
* 加權(quán)無向圖的實(shí)現(xiàn)
*
* @author alvin
* @date 2022/11/3
* @since 1.0
**/
public class EdgeWeightedGraph {
//頂點(diǎn)總數(shù)
private final int V;
//邊的總數(shù)
private int E;
//鄰接表
private Queue<Edge>[] adj;
//創(chuàng)建一個(gè)含有V個(gè)頂點(diǎn)的空加權(quán)無向圖
public EdgeWeightedGraph(int V) {
//初始化頂點(diǎn)數(shù)量
this.V = V;
//初始化邊的數(shù)量
this.E = 0;
//初始化鄰接表
this.adj = new Queue[V];
for (int i = 0; i < adj.length; i++) {
adj[i] = new ArrayDeque<>();
}
}
//獲取圖中頂點(diǎn)的數(shù)量
public int V() {
return V;
}
//獲取圖中邊的數(shù)量
public int E() {
return E;
}
//向加權(quán)無向圖中添加一條邊e
public void addEdge(Edge e) {
//需要讓邊e同時(shí)出現(xiàn)在e這個(gè)邊的兩個(gè)頂點(diǎn)的鄰接表中
int v = e.either();
int w = e.other(v);
adj[v].add(e);
adj[w].add(e);
//邊的數(shù)量+1
E++;
}
//獲取和頂點(diǎn)v關(guān)聯(lián)的所有邊
public Queue<Edge> adj(int v) {
return adj[v];
}
//獲取加權(quán)無向圖的所有邊
public Queue<Edge> edges() {
//創(chuàng)建一個(gè)隊(duì)列對(duì)象,存儲(chǔ)所有的邊
Queue<Edge> allEdges = new ArrayDeque<>();
//遍歷圖中的每一個(gè)頂點(diǎn),找到該頂點(diǎn)的鄰接表,鄰接表中存儲(chǔ)了該頂點(diǎn)關(guān)聯(lián)的每一條邊
//因?yàn)檫@是無向圖,所以同一條邊同時(shí)出現(xiàn)在了它關(guān)聯(lián)的兩個(gè)頂點(diǎn)的鄰接表中,需要讓一條邊只記錄一次;
for (int v = 0; v < V; v++) {
//遍歷v頂點(diǎn)的鄰接表,找到每一條和v關(guān)聯(lián)的邊
for (Edge e : adj(v)) {
if (e.other(v) < v) {
allEdges.add(e);
}
}
}
return allEdges;
}
}到此這篇關(guān)于Java數(shù)據(jù)結(jié)構(gòu)之加權(quán)無向圖的設(shè)計(jì)實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Java加權(quán)無向圖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 帶你了解Java數(shù)據(jù)結(jié)構(gòu)和算法之無權(quán)無向圖
- Java實(shí)現(xiàn)無向圖的示例詳解
- Java數(shù)據(jù)結(jié)構(gòu)之圖的基礎(chǔ)概念和數(shù)據(jù)模型詳解
- Java數(shù)據(jù)結(jié)構(gòu)之圖的兩種搜索算法詳解
- Java數(shù)據(jù)結(jié)構(gòu)之圖的路徑查找算法詳解
- Java數(shù)據(jù)結(jié)構(gòu)之有向圖設(shè)計(jì)與實(shí)現(xiàn)詳解
- Java數(shù)據(jù)結(jié)構(gòu)之有向圖的拓?fù)渑判蛟斀?/a>
相關(guān)文章
springboot項(xiàng)目實(shí)現(xiàn)多數(shù)據(jù)源配置使用dynamic-datasource-spring-boot-starter
這篇文章主要介紹了springboot項(xiàng)目實(shí)現(xiàn)多數(shù)據(jù)源配置使用dynamic-datasource-spring-boot-starter,本文分步驟結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-06-06
SpringBoot配置動(dòng)態(tài)數(shù)據(jù)源的實(shí)戰(zhàn)詳解
Spring對(duì)數(shù)據(jù)源的管理類似于策略模式,不懂策略模式也沒關(guān)系,其實(shí)就是有一個(gè)全局的鍵值對(duì),類型是Map<String, DataSource>,當(dāng)JDBC操作數(shù)據(jù)庫(kù)之時(shí),會(huì)根據(jù)不同的key值選擇不同的數(shù)據(jù)源,本文介紹了SpringBoot配置動(dòng)態(tài)數(shù)據(jù)源的方法,需要的朋友可以參考下2024-08-08
Java實(shí)現(xiàn)整合文件上傳到FastDFS的方法詳細(xì)
FastDFS是一個(gè)開源的輕量級(jí)分布式文件系統(tǒng),對(duì)文件進(jìn)行管理,功能包括:文件存儲(chǔ)、文件同步、文件上傳、文件下載等,解決了大容量存儲(chǔ)和負(fù)載均衡的問題。本文將提供Java將文件上傳至FastDFS的示例代碼,需要的參考一下2022-02-02
Java責(zé)任鏈設(shè)計(jì)模式實(shí)例分析
這篇文章主要介紹了Java責(zé)任鏈設(shè)計(jì)模式,結(jié)合實(shí)例形式詳細(xì)分析了Java責(zé)任鏈設(shè)計(jì)模式的原理與相關(guān)操作技巧,需要的朋友可以參考下2019-07-07
Spring-IOC容器-Bean管理-基于XML方式超詳解
這篇文章主要介紹了Spring為IOC容器Bean的管理,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2021-08-08

