# 无向图：

public class LinkedList<T> {
private Integer N = 0;
private Node<T> root;

//链表的结点
@SuppressWarnings("hiding")
class Node<T> {
T value;
Node<T> next;

public Node(T t,Node<T> node) {
this.value = t;
this.next = node;
}
}

//添加一个结点
if(root == null)
root = node;
else {
Node<T> temp = root;
root = node;
root.next = temp;
}
N++;
}

Node<T> node = new Node<T>(t,null);
if(root == null)
root = node;
else {
Node<T> temp = root;
root = node;
root.next = temp;
}
N++;
}

//链表的节点数
public Integer size() {
return N;
}

public Node<T> getRoot() {
return root;
}

//遍历链表
public void traverse() {
Node<T> node = root;
while(node != null) {
System.out.print(node.value + " ");
node = node.next;
}
}

//获取链表上的所有节点的值，返回一个数组
return null;

Integer i = 0;
while(node != null) {
result[i++] = (Integer)node.value;
node = node.next;
}
return result;
}
}

public class UndiGraphBase {
//顶点数目
private Integer V;

//边的数目
private Integer E;

//邻接表

//创建一个含有V个顶点但不含有边的图
@SuppressWarnings("unchecked")
void graph(Integer V) {
this.V = V;
this.E = 0;
for(int v=0;v<V;v++) {
}
}

public Integer V() {
return V;
}

public Integer E() {
return E;
}

//添加一条边
public void addEdge(Integer v,Integer w) {
E++;
}

//遍历
public void traverse() {
for(int i=0;i<V;i++) {
System.out.print(i + ": ");
System.out.println();
}
}

//获取某个顶点所有相邻的顶点
public Integer[] getAllValueByIndex(Integer i) {
}
}

# 深度优先遍历

public class Instance {
public static UndiGraphBase getInstance() {
UndiGraphBase undiGraphBase = new UndiGraphBase();
undiGraphBase.graph(13);
return undiGraphBase;
}
}

public class DepthFirstPath {
//所有顶点组成的数组，如果起点到某顶点可达，则为true，否则为false
private boolean[] marked;

//起点
private final Integer startV;

//用数组来表示路径树，表示起点到可达顶点的路径。保存的是到达此顶点的上一个顶点
private Integer[] edgeTo;

public DepthFirstPath(UndiGraphBase G,Integer startV) {
marked = new boolean[G.V()];
edgeTo = new Integer[G.V()];
this.startV = startV;
dfs(G,startV);
}

public void dfs(UndiGraphBase G,Integer v) {
marked[v] = true;
Integer[] allNodeValues = G.getAllValueByIndex(v);
if(allNodeValues == null)
return;

for(int i=0;i<allNodeValues.length;i++) {
if((!marked[allNodeValues[i]])) {
edgeTo[allNodeValues[i]] = v;
dfs(G,allNodeValues[i]);
}
}
}

//获取顶点到v的路径
public void getPath(UndiGraphBase G,Integer v) {
if(!hasPathTo(v))
return;

//存储路径
Stack<Integer> path = new Stack<Integer>();
for(int i=v;i!=startV;i = edgeTo[i])
path.push(i);

//加入起点
path.push(startV);

//打印栈（即起点startV到v的路径）
System.out.println(path.toString());
}

//从起点startV是否有路径通往v（即是否可达）
public boolean hasPathTo(Integer v) {
return marked[v];
}

public static void main(String[] args) {
UndiGraphBase G = Instance.getInstance();
DepthFirstPath depthFirstPath = new DepthFirstPath(G,0);
depthFirstPath.getPath(G, 3);
}
}

# 广度优先遍历

public class BreadthFirstPath {
//到达该顶点的最短路径是否已知
private boolean[] marked;

//到达该顶点的已知路径上的最后一个顶点
private Integer[] edgeTo;

//起点
private final Integer start;

marked = new boolean[G.V()];
edgeTo = new Integer[G.V()];
this.start = start;
bfs(G,start);
}

private void bfs(UndiGraphBase G,Integer start) {
//标记起点
marked[start] = true;

while(!queue.isEmpty()) {
//从队列中删除下一顶点
Integer v = queue.remove();

Integer[] allNodeValues = G.getAllValueByIndex(v);
for(int i=0;i<allNodeValues.length;i++) {
//对于每个未被标记的顶点
if(!marked[allNodeValues[i]]) {
//保存最短路径的最后一个顶点
edgeTo[allNodeValues[i]] = v;
//标记它，因为最短路径已知
marked[allNodeValues[i]] = true;
}
}
}
}

public boolean hasPathTo(Integer v) {
return marked[v];
}

//获取顶点到v的路径
public void getPath(UndiGraphBase G,Integer v) {
if(!hasPathTo(v))
return;

//存储路径
Stack<Integer> path = new Stack<Integer>();
for(int i=v;i!=start;i = edgeTo[i])
path.push(i);

//加入起点
path.push(start);

//打印栈（即起点startV到v的路径）
System.out.println(path.toString());
}

public static void main(String[] args) {
UndiGraphBase G = Instance.getInstance();
}
}

# 使用深度优先遍历获取图中的所有连通分量

public class ConnectedComponent {
//顶点是否联通
private boolean[] marked;

//联通分量标识符
private Integer[] id;

//联通分量数目
private Integer count = 0;

public ConnectedComponent(UndiGraphBase G) {
marked = new boolean[G.V()];
id = new Integer[G.V()];
for(int i=0;i<G.V();i++) {
if(!marked[i]) {
dfs(G,i);
count++;
}
}
}

public void dfs(UndiGraphBase G,Integer v) {
marked[v] = true;
id[v] = count;

Integer[] allNodeValues = G.getAllValueByIndex(v);
for(int i=0;i<allNodeValues.length;i++) {
if((!marked[allNodeValues[i]]))
dfs(G,allNodeValues[i]);
}
}

//判断v和w是否联通
public boolean connected(Integer v,Integer w) {
return id[v] == id[w];
}

//连通分量数
public Integer count() {
return count;
}

//v顶点所在的联通分量的标识符（0-count()-1）
public Integer id(Integer v) {
return id[v];
}

public Integer[] getID() {
return id;
}

public static void main(String[] args) {
UndiGraphBase G = Instance.getInstance();
ConnectedComponent cc = new ConnectedComponent(G);

Integer m = cc.count();
System.out.println(m + " components");

Integer[] id = cc.getID();

for(int j=0;j<m;j++) {
for(int i=0;i<id.length;i++) {
if(id[i] == j) {
System.out.print(i + " ");
}
}
System.out.println();
}

}
}

Id数组表示索引所代表的顶点属于哪个连通分量，假如一个图总共有n个分量，那么各个连通分量分别用0,1,2....n-1表示，id数组的值即是该顶点属于第几个连通分量。

# 广度优先遍历与深度优先遍历的区别

posted @ 2015-09-14 09:55  @瞪着太阳的乌鸦  阅读(23751)  评论(1编辑  收藏