图的定义:由一组顶点和一组能够将两个顶点相连的边组成的数据结构.
图的常用表示方法
邻接矩阵:使用矩阵表示,当顶点v和w连接在一起时,就把v行w列定义为true,否则为false,但大量数据时所需空间不能满足.
边的数组:使用一个Edge类,含有两个变量,对应边上的顶点.
邻接表数组:以顶点为索引的列表数组,数组中的每个元素都是和该顶点邻接的顶点.
连通图:从任意一个顶点都存在一条路径到达另一个任意顶点,如果一个非连通图由若干连通的部分组成,它们都是极大连通子图.
图的密度是指已经连接的顶点对所占所有可能连接的顶点对的比例.在稀疏图中,被连接的顶点对很少,而在稠密图中,只有少部分顶点对之间没有边连接.
二分图是一种能够将所有节点分为两部分的图,其中图的每条边所连接的两个顶点都分别属于不同的部分.
利用深度优先搜索寻找路径
public class DepthFirstPaths { private boolean[] marked; //是否调用过dfs private int[] edgeTo; //从起点到一个顶点已知路径上的最后一个顶点 private final int s; //起点 public DepthFirstPaths(Graph G,int s){ marked = new boolean[G.V()]; edgeTo = new int[G.V()]; this.s = s; dfs(G,s); } public void dfs(Graph G, int v){ marked[v] = true; //标记为已调用 for(int w:G.adj(v)){ //遍历该顶点所有邻接点 if(!marked[w]){ edgeTo[w] = v; //最后到达w的顶点 dfs(G,w); } } } public boolean hasPathTo(int v){ return marked[v]; } //遍历从出发点s到顶点v的路径 public Iterable<Integer> pathTo(int v){ if(!hasPathTo(v)) return null; Stack<Integer> path = new Stack<Integer>(); for(int x = v; x != s; x=edgeTo[x]){ path.push(x); } path.push(s); return path; } public static void main(String[] args) { // TODO Auto-generated method stub } }
利用广度优先搜索寻找路径
public class BreadthFirstPaths { private boolean[] marked; private int[] edgeTo; private final int s; public BreadthFirstPaths(Graph G, int s){ marked = new boolean[G.V()]; edgeTo = new int[G.V()]; this.s = s; bfs(G,s); } private void bfs(Graph G,int s){ Queue<Integer> queue = new Queue<Integer>(); marked[s] = true; //起点存入队列 queue.enqueue(s); while(!queue.isEmpty()){ //删除顶点 int v = queue.dequeue(); for(int w:G.adj(v)){ if(!marked[w]){ edgeTo[w] = v; marked[w] = true; queue.enqueue(w); } } } } public static void main(String[] args) { // TODO Auto-generated method stub } }