图论 Graph Theory
图论涉及到的地方
交通运输、社交网络、互联网、工作安排、脑区活动、程序状态执行
比如交通运输
点代表着一个城市 而连接的线代表着另一个城市与这个城市的道路
社交网络这可以这样认为:点代表着人,连接代表着这个人是这个人的好友
图的分类
无向图 如人与人之间的认识(这个点连接过去,还要返回过去)
有向图 一个事件转移到另一个事件 有方向
权值
边的权重(或者称为权值、开销、长度等),也是一个非常核心的概念,即每条边都有与之对应的值。
比如交通运输,这个城市到另一个城市的边需要多少距离 这就是这个边的权值
有权图
无权图、边上没有值
有权上就有
自环边只有它自身的边
平行边:两个节点有多条连接的边 如城市交通 一个城市到另一个城市 有多条路一样的道理
稀疏图
稠密图
领接表适合表示稀疏图
领接矩阵符合表示稠密图
稀疏图 -邻接表从
这个是无向图。。
一个节点 一个节点的来
0只有与1有链接 就是 0 1
1有 0 1 3 2 最后就是 1 0 2 3
其他继续这样
这个是有向图
0只指向了1 结果 0 1
1指向了2 结果 1 2
代码
package com.binglian.Graph;
import java.awt.event.MouseWheelEvent;
import java.util.Vector;
//稀疏图 -邻接表
public class SparseGraph {
private int n;//节点数
private int m;//边数
private boolean directed; //是否为有向图
private Vector<Integer>[] g;//图的具体数据
public SparseGraph(int n,boolean directed){
assert n>=0;
this.n=n;
this.m=0;
this.directed=directed;
//g初始化为n个空的vector,表示每一个g[i]都为空,即没有任何边
g=(Vector<Integer>[])new Vector[n];
for(int i=0;i<n;i++)
g[i]=new Vector<Integer>();
}
//返回节点个数
public int V(){
return n;
}
//返回边的个数
public int E(){
return m;
}
//向图中添加一个
public void addEdge(int v,int w){
assert v>=0 && v<n;
assert w>=0 && w<n;
g[v].add(w);
if(v!=w && ! directed)
g[w].add(v);
m++;
}
//验证图中是否从v到w的边
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)==w)
return true;
return false;
}
//返回图中一个顶点的所有邻边
//由于java使用引用机制,返回一个Vector不会带来额外开销
public Iterable<Integer> adj(int v){
assert v>=0 && v<n;
return g[v];
}
}
稠密图 -邻接矩阵
这个n个节点的二维数组
n*n
0 1 2 3 这个是节点对应的
0和1连接 说明 在1的下面就是1 为真 连接
1和 2 3 0 都连接 那么 0 2 3都为1
2 和1 3连接 那么 1的连接
有向矩阵
和有向表差不多
package com.binglian.Graph;
import java.util.Vector;
//稠密图 -邻接矩阵
public class DenseGraph {
private int n;//节点数
private int m;//边数
private boolean directed;//是否为有向图
private boolean[][] g;//图的具体数据
//构造函数
public DenseGraph(int n,boolean directed){
assert n>=0;//断言
this.n=n;
this.m=0;//初始化没有边
this.directed=directed;
//g初始化为n*n的布尔矩阵,每一个g[i][j]均为false,表示为没有任何边
//false为boolean型的默认值;
g=new boolean[n][n];
}
//返回节点个数
public int V(){
return n;
}
//返回边的个数
public int E(){
return m;
}
//向图中添加一个边
public void addEdge(int v,int w){
assert v >= 0 && v < n ;
assert w >= 0 && w < n ;
if(hasEdge(v,w))
return ;
g[v][w]=true;
if(!directed)
g[w][v]=true;//如果是无向图的话 需要在相互连接
m++;
}
//返回图中一个顶点的所有邻边
//由于java1使用引用机制,返回一个Vector不会带来额外开销
public Iterable<Integer> adj(int v){
assert v>=0 && v<n;
Vector<Integer> adjv=new Vector<Integer>();
for(int i=0;i<n;i++)
if(g[v][i])
adjv.add(i);
return adjv;
}
//验证图中是否从v到w的边
boolean hasEdge(int v,int w){
assert v>=0 && v<n;
assert w>=0 && w<n;
return g[v][w];
}
}