图
图的算法是树的扩展,树从上向下,结点都有父节点,而图每个结点都是平等的。
图分为:无向图,有向图,加权图,加权有向图
应用:
地图,正在旅行的人想知道,某两个地点的最短路径。对最短路径上经历过交通堵塞的人,可能想知道哪条线路最快。
网页信息,我们在浏览网页时,页面上都包含其他网页的链接,跳的另一个网页。整个互联网就是一张图。图算法是帮我们在网络上定位信息的搜索引擎的关键组件。
电路,一块电路板,晶体管、电阻、电容等等元件连接在一起。我们用计算机制造电路板的机器,并检查电路板的功能是否正常。
任务调度,商品的成产过程包含许多工序,这些条件决定任务的先后顺序。
无向图
图是由一组顶点和一组能够将两个顶点相连的边组成的。
特殊的图:自环,即一条连接一个顶点和其他自身的边。 和,连接同一对顶点的两条边称为平行边
术语: 当两个顶点通过一条边相连,我们称这两个顶点相邻。称该连接依附于这两个顶点。
某个顶点的度数即,依附于它的变数总和。
子图是由一幅图的所有边的一个子集(以及他们所依附的所有顶点)组成的图。
路径是由边顺序连接的一系列的顶点。
简单路径是一条没有重复顶点的路径。
环是一条至少含一条边且起点和终点相同的路径。
简单环是一条(除了起点和终点必须相同之外)不含重复顶点和边的环。
树是一幅无环连通图。互不相连的树组成的集合叫森林。
图的密度指,已经连接的顶点对占所有可能被连接的顶点对的比例。
稀疏图,被连接的顶点对很少。
稠密图,只有少部分没有连接。
二分图,是一种能将所有节点分为两部分的图。
代码表示图:
publich class Graoh{
private int v; //顶点数
private int e; //边数
//向图中添加一条边v-w
publich void addEdge(int v, int w){
}
//和v相邻的所有顶点
publich Iterator<Integer> adj(int v){
}
//图的表示
publich String toString(){
String s = v+":vertices, "+e+":edges\n";
for(int i=0; i<v ;i++){
s+=v+":";
for(int j: this.adj(v)){
s+=w+": ";
}
s+="\n";
}
return s;
}
//计算v的度
public static int degree(Graph g, int v){
int degree = 0;
for(int w : g.adj(v)){
degree++;
}
return degree;
}
}
无向图的表示方法:
1.邻接矩阵
使用一个V*V的布尔矩阵。当顶点V和W之间有相连接的边时,定义V行W列为true。否则为false。但是这样就需要v*v的数组空间。占用空间较大。因为稀疏图常见,所以很多控件浪费。
2.边的数组
用一个数组来存放所有的边。数组大小为E(数组每个对象,它含有两个int变量表示两个相连的顶点),但是因为我们操作总是需要访问,某个顶点的相邻结点。对于这种,要访问相邻结点必须遍历整个数组。造成效率低下。
3.邻接表数组
使用一个以顶点为索引的列表数组。数组的每个元素都是链表的表头。链表存放对应下标的节点所所连接的边
深度优先搜索(dfs):
搜索图中所以的节点,就像走迷宫,探索所有迷宫的道路。
1.选择一条没有标记的路,一边走一边铺绳子
2.标记走过的路
3.当走到一个已经标记的结点的地方,我们要回退,根据绳子回退到上一个地方。
4.如果回退的地方没有未标记的路,则继续回退,否则,走未标记的路
绳子保证你总能找出一条出路。标记则保证你不会两次经过同一条通道。
广度优先搜索(bfs):
解决:给定一个图,一个起点s,从s到顶点v是否存在一条路径?如果有,找出其中最短的那条。
根据距离进行搜索。先搜索所有距离为1的地方。如果没找到,搜索距离为2的地方。
深度搜索,搜索的规则是,先进后出
广度搜索,则是,先进先出
连通分量(深度优先搜索的实现)
找出一副图的所有连通分量。
从图某一点出发,不可能遍历图所有的顶点。只能访问到该顶点所在的最大连通子图(连通分量)的所有顶点。。这些顶点的图,就构成一个连通分量。
对图每一个顶点检测,如果已被访问,则顶点一定是在已知的连通分量上。如果还未被访问,则从该顶点出发遍历图,求得另一个连通分量。
符号图
图都是通过文件或者网页定义的。使用的是字符串而非整数来表示和指代顶点
顶点不是1,2,3而是字符串
用指定的分隔符隔开顶点名,空格