目录
带权图
带权图java代码实现
最小生成树
Kruskal算法
切分定理
Kruskal算法的java代码实现
Prim算法
Prim算法的java代码实现
总结
带权图
边上的权是附加的额外信息,可以代表不同公路的收费等你需要的信息。
带权图java代码实现
port java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.TreeMap;
import java.util.Scanner;
import java.util.TreeSet;
//暂时支持无向带权图
public class WeightedGraph {
private int V;
private int E;
//TreeMap传入的第二个元素是权值类型
// 我们这里用的是Integer,具体用什么可以自行修改
private TreeMap<Integer, Integer>[] adj;
public WeightedGraph(String file){
File file = new File(filename);
try(Scanner scanner = new Scanner(file)){
V = scanner.nextInt();//读取顶点信息
if(V < 0) throw new IllegalArgumentException("V must be non-negative");
adj = new TreeMap[V];
for(int i = 0; i < V; i++){
adj[i] = new TreeMap<Integer, Integer>();
}
E = scanner.nextInt();//读取边的信息
if(E < 0) throw new IllegalArgumentException("E must be non-negative");
for(int i = 0; i < E; i++){
int a = scanner.nextInt();
validateVertex(a);
int b = scanner.nextInt();
validateVertex(b);//判断合法性
int wight = scanner.nextInt();//读取权值
//不要自环边
if(a == b) throw new IllegalArgumentException("Self Loop is Detected!");
//不要平行边
if(adj[a].containsKey(b)) throw new IllegalArgumentException("");
adj[a].put(b, weight);//传入weight
adj[b].put(a, weight);
}
}
catch(IOException e){
e.printStackTrace();
}
}
public void validateVertex(int v) {
if (v < 0 || v >= V) {
throw new IllegalArgumentException("vertex" + "is invalid");
}
}
public int V() {return V;}
public int E() {return E;}
public boolean hasEdge(int v, int w){
validateVertex(v);
validateVertex(w);
return adj[v].containsKey(w);
}
//返回和v相邻的所有顶点
public Iterable<Integer> adj(int v){
validateVertex(v);
return adj[v].keySet();//返回TreeMap中所有的键
}
//返回权值
public int getWeight(int v, int w){
if(hasEdge(v, w))
return adj[v].get(w);//获得w这个键对应的权值
throw new IllegalArgumentException(String.format("no edge %d - %d", v, w));
}
public int degree(int v){
validateVertex(v);
return adj[v].size();
}
public void removeEdge(int v, int w){
validateVertex(v);
validateVertex(w);
adj[v].remove(w);
adj[w].remove(v);
}
@Override
public Object clone(){
try{
WeightedGraph cloned = (WeightedGraph) super.clone();
cloned.adj = new TreeMap[V];
for(int v = 0; v < V; v++){
cloned.adj[v] = new TreeMap<Integer, Integer>();
for(Map.Entry<Integer, Integer>entry : adj[v].entrySet())
cloned.adj[v].put(entry.getKey(), entry.getValue());
}
return cloned;
}
catch(CloneNotSupportedException e){
e.printStackTrace();
}
return null;
}
@Override
public String toString(){
StringBuilder sb = new StringBuilder();
sb.append(String.format("V = %d, E = %d\n"), V, E);
for(int v = 0; v < V; v++){
sb.append(String.format("%d : ", v));
for(Map.Entry<Integer, Integer>entry : adj[v].entrySet())
sb.append(String.format("(%d : %d)", entry.getKey(), entry.getValue()));
sb.append('\n');
}
return sb.toString();
}
public static void main(String[]args){
WeightedGraph g = new WeightedGraph("g.txt");
System.out.println(g);
}
}
最小生成树
Kruskal算法
同一张图的不同生成树的权值和大小不同,最小生成树就是求权值和最小的生成树。
在选最短的边的同时要注意不要和已选的边形成环。如下图,我们成功选了六条边连接了七个顶点,形成了最小生成树。
切分定理
Kruskal算法的java代码实现
import java.util.ArrayList;
import java.util.Collections;
public class Kruskal {
private WeightedGraph G;
private ArrayList<WeightedEdge> mst;
public Kruskal(WeightedGraph G){
this.G = G;
mst = new ArrayList<>();
CC cc = new CC(G);
if(cc.count() > 1) return;
ArrayList<WeightedEdge> edges = new ArrayList<>();
for(int v = 0; v < G.V(); v ++)
for(int w: G.adj(v))
if(v < w)
edges.add(new WeightedEdge(v, w, G.getWeight(v, w)));
Collections.sort(edges);
UF uf = new UF(G.V());
for(WeightedEdge edge: edges){
int v = edge.getV();
int w = edge.getW();
if(!uf.isConnected(v, w)){
mst.add(edge);
uf.unionElements(v, w);
}
}
}
public ArrayList<WeightedEdge> result(){
return mst;
}
public static void main(String[] args){
WeightedGraph g = new WeightedGraph("g.txt");
Kruskal kruskal = new Kruskal(g);
System.out.println(kruskal.result());
}
}
Prim算法
Prim算法的java代码实现
import java.util.ArrayList;
import java.util.Queue;
import java.util.PriorityQueue;
public class Prim {
private WeightedGraph G;
private ArrayList<WeightedEdge> mst;
public Prim(WeightedGraph G){
this.G = G;
mst = new ArrayList<>();
CC cc = new CC(G);
if(cc.count() > 1) return;
boolean visited[] = new boolean[G.V()];
visited[0] = true;
Queue pq = new PriorityQueue<WeightedEdge>();
for(int w: G.adj(0))
pq.add(new WeightedEdge(0, w, G.getWeight(0, w)));
while(!pq.isEmpty()){
WeightedEdge minEdge = (WeightedEdge) pq.remove();
if(visited[minEdge.getV()] && visited[minEdge.getW()])
continue;
mst.add(minEdge);
int newv = visited[minEdge.getV()] ? minEdge.getW() : minEdge.getV();
visited[newv] = true;
for(int w: G.adj(newv))
if(!visited[w])
pq.add(new WeightedEdge(newv, w, G.getWeight(newv, w)));
}
}
public ArrayList<WeightedEdge> result(){
return mst;
}
public static void main(String[] args){
WeightedGraph g = new WeightedGraph("g.txt");
Prim prim = new Prim(g);
System.out.println(prim.result());
}
}